ANSI_null在TSQL中如何工作?

ANSI_null在TSQL中如何工作?,tsql,sql-server-2008,null,Tsql,Sql Server 2008,Null,SET ANSI_NULLS OFF在TSQL中似乎给出了不同的结果,这取决于您是比较表中的字段还是值。有人能帮我理解为什么最后两个查询没有结果吗?我不是在寻找解决方案,只是一个解释 select 1 as 'Col' into #a select NULL as 'Col' into #b --This query gives results, as expected. SET ANSI_NULLS OFF select * from #b where NULL = Col --Thi

SET ANSI_NULLS OFF
在TSQL中似乎给出了不同的结果,这取决于您是比较表中的字段还是值。有人能帮我理解为什么最后两个查询没有结果吗?我不是在寻找解决方案,只是一个解释

select 1 as 'Col' into #a
select NULL as 'Col' into #b

--This query gives results, as expected.  
SET ANSI_NULLS OFF
select * from #b
where NULL = Col

--This query gives results, as expected.
SET ANSI_NULLS OFF
select * from #a
where NULL != Col

--This workaround gives results, too.
select * from #a a, #b b
where isnull(a.Col, '') != isnull(b.Col, '')

--This query gives no results, why?
SET ANSI_NULLS OFF
select * from #a a, #b b
where a.Col != b.Col

--This query gives no results, why?
SET ANSI_NULLS OFF
select * from #a a, #b b
where b.Col != a.Col

任何与空值相比的操作都会失败。即使比较两个空值也会失败。甚至是将由于(IMHO)愚蠢地处理NULL而失败

也就是说查询可以改写为:

select * from #a a where a.Col not in (select b.Col from #b b)
最后一个查询与第二个到最后一个查询相同,因为比较的顺序无关紧要

顺便说一句,您的解决方法之所以有效,是因为您正在测试#b.Col列中的空值,并显式地将其转换为“”,然后允许您的查询在它们之间进行字符串比较。另一种写作方式是:

select * from #a a, #b b
where a.Col != COALESCE(b.Col, '')

最后两个查询失败的原因是
SET ANSI_NULLS ON/OFF
仅在与变量或空值进行比较时适用。在比较列值时,它不适用。从BOL:

将ANSI_null设置为ON会影响比较 仅当 比较要么是一个变量 是NULL或文本NULL。如果两者都有 比较的边是列或列 复合表达式,则设置不起作用 不影响比较


@rossfabricant-禁用ANSI_NULLS的功能只有在向后兼容的情况下才有可能实现(即,设置该功能的原因可以在一只手上计算,手指剩余)。所以,我怀疑原因一定是因为以前的SQL实现是以这种方式运行的。我只是偶然发现了这一点,我发现这与我以前从未知道的有关。我一直认为SQL的行为与Java/.NET等中比较NULL的方式相同。