SET IGNORE_FOR_AS_LONG_AS_POSSIBLE_EVERYTHING_TO_DO_WITH_ANSI_SETTINGS ON
Most likely your databases are working sufficiently well that you don't want to even think about digging into ANSI standards and aligning your settings with the rest of the world. But, if you look in the BOL index for "null values [SQL Server], comparison operators" you'll see an important message stating that ANSI_NULLS will be forced ON in a future release. And believe me, if you haven't looked into this, you probably have lurking bugs in your code.
If you read the remarks underneath the message, you'll see that things get confusing and buggy when comparing null columns and variables. It took me a while to decipher exactly which settings makes everyone happy. I'll show you the five simple steps I've taken to get through this quagmire to get back to producing bug free code on the ANSI bandwagon.
1) First go into SSMS and go into Tools > Options > Query Execution > SQL Server > ANSI and press the button labeled "Reset to Default" so we are working with the same connection settings.
2) Make sure your databases have the correct settings since they affect object creation settings. At the very least, try to get model updated so new databases will be created correctly.
-- list databases and their ANSI settings select name, case when is_ansi_null_default_on = 1 and is_ansi_nulls_on=1 and is_ansi_padding_on=1 and is_ansi_warnings_on=1 and is_arithabort_on=1 and is_concat_null_yields_null_on=1 and is_numeric_roundabort_on=0 and is_quoted_identifier_on=1 then 'ANSI' else 'not' end from sys.databases order by name
3) Make sure your objects were created with the correct settings by running the next six selects. The tables are the hardest to fix, since they will need scripted and recreated. You can trick the scripter into making a script by making a minor column change such as nullability, then manually changing it back in the generated code. If you don't have the willpower to fix these objects right now, please continue on to steps 4 and 5.
select name as 'Table Not ANSI', uses_ansi_nulls from sys.tables where uses_ansi_nulls <> 1 order by name select name as 'Proc Not ANSI', objectproperty(object_id, 'ExecIsAnsiNullsOn') as AnsiNullsOn, objectproperty(object_id, 'ExecIsQuotedIdentOn') as QuotedIdentOn from sys.procedures where (isnull(objectproperty(object_id, 'ExecIsAnsiNullsOn'),0)=0 or isnull(objectproperty(object_id, 'ExecIsQuotedIdentOn'),0)=0) and name not in (select cast(cast(assembly_method as varbinary(100)) as varchar(100)) from sys.assembly_modules) order by name select name as 'Trigger Not ANSI', objectproperty(object_id, 'ExecIsAnsiNullsOn') as AnsiNullsOn, objectproperty(object_id, 'ExecIsQuotedIdentOn') as QuotedIdentOn from sys.triggers where (isnull(objectproperty(object_id, 'ExecIsAnsiNullsOn'),0)=0 or isnull(objectproperty(object_id, 'ExecIsQuotedIdentOn'),0)=0) order by name select name as 'View Not ANSI', objectproperty(object_id, 'ExecIsAnsiNullsOn') as AnsiNullsOn, objectproperty(object_id, 'ExecIsQuotedIdentOn') as QuotedIdentOn from sys.views where (isnull(objectproperty(object_id, 'ExecIsAnsiNullsOn'),0)=0 or isnull(objectproperty(object_id, 'ExecIsQuotedIdentOn'),0)=0) order by name select name as 'Function Not ANSI', objectproperty(object_id, 'ExecIsAnsiNullsOn') as AnsiNullsOn, objectproperty(object_id, 'ExecIsQuotedIdentOn') as QuotedIdentOn from sys.objects where (isnull(objectproperty(object_id, 'ExecIsAnsiNullsOn'),0)=0 or isnull(objectproperty(object_id, 'ExecIsQuotedIdentOn'),0)=0) and type = 'FN' order by name select object_name(object_id) as 'Column Not ANSI', c.*, t.name --select distinct t.name from sys.columns c join sys.types t on c.system_type_id = t.system_type_id where is_ansi_padded =0 and t.name in ('nchar') and object_name(object_id) <> 'sysfiles1'
4) Fix lurking bugs by replacing all "= null" with "is null" since this will work regardless of ANSI settings. Also, replace all "<> null" with "is not null".
--Run the following query to return a list of objects that might need changed. -- Some false positives are returned since initializing with "set @v = null" is a valid ANSI statement. select distinct 'exec sp_helptext '+object_name(id) from sys.syscomments where text like '%= null%' order by 1
5) You can use the following function anytime you need to do a nullable ints comparision in your t-sql. This is only necessary when comparing a variable to a column. This happens quite often with stored procedure parameters in "where" clauses. It would have been nice for this to have been built into t-sql. You may need to make another function called NullableVarcharsMatch.
-- compare nullable int variables -- return true if the value matches or if both parameters are null create function [dbo].[NullableIntsMatch] (@a int, @b int) returns Bit as -- written by Bill Talada begin -- no need to call this function if @a and @b are both columns -- function calls are slow...so if you want to inline the tests, use one of the following lines... --same: where ((@a = @b) or (@a is null and @b is null)) --diff: where ((@a <> @b) or (@a is null and @b is not null) or (@a is not null and @b is null)) declare @r bit if @a = @b or (@a is null and @b is null) set @r=1 else set @r=0 return (@r) end GO
Good work! Rest assured your queries will no longer be "missing" rows.