为什么SET ANSI_NULLS OFF无法比较字段?

alp*_*pav 4 sql database sql-server null sql-server-2008-r2

我认为SET ANSI_NULLS OFF模式非常方便,并且如果它一致地工作,它将默认使用它 - 允许使用=或!=无处不在比较空值.但它只有在我与显式内联null进行比较时才有效,但如果我与包含null的字段进行比较 - 它就不起作用了.为什么微软会这样设计呢?难怪为什么没有人默认使用SET ANSI_NULLS OFF模式.我宁愿忍受"is null"和"is not null"的痛苦而不是考虑我使用内联和什么不是.

这是显示问题的例子 - 与???一致 应该返回2行,但它只返回一行.

CREATE TABLE t1 (a int null, b int null)
INSERT INTO t1 values (null,null)
INSERT INTO t1 values (0,null)
INSERT INTO t1 values (null,0)
INSERT INTO t1 values (0,0)
set ansi_nulls ON
select * from t1 where a=null -- empty result
select * from t1 where a=b  -- (0,0)
select * from t1 where null=null -- empty result
set ansi_nulls OFF
select * from t1 where a=null -- (null,null),(null,0)
select * from t1 where a=b -- why only (0,0) ???, it should be (0,0),(null,null)
select * from t1 where null=null -- returns all 4 rows
drop table t1
Run Code Online (Sandbox Code Playgroud)

Bri*_*ats 6

这回答了这里:

ANSI_NULLS如何在TSQL中工作?

如果其中一个操作数是空变量或文字空值,则设置ansi_nulls off仅影响比较.

此外,您不应使用off设置编写任何新代码,因为将来不支持它:

http://msdn.microsoft.com/en-us/library/ms188048.aspx

更新:

重新阅读你的问题之后,我认为你实际上是在解释为什么不这样做:

select * from t1 where a=b
Run Code Online (Sandbox Code Playgroud)

功能如下:

select * from t1 where a=b or (a=null and b=null)
Run Code Online (Sandbox Code Playgroud)

它将在您的示例中返回(null,null),(0,0).

所以,您正在检查两个条件:

  1. 两个列值都相等
  2. 两个列值都是未知的

当你的表达式被写为a = null时,你很清楚你想要做什么.但是如果写成a = b,你打算只检查第一个条件,还是两者都检查?

另一种思考方式,比如你正在编写一个查询来返回所有拥有相同家庭+手机号码的客户.您是否希望返回这两列中具有空值的客户?

简而言之,MSFT不希望在只有一个条件时自动检查两个条件 - 我认为这是正确的设计.

  • OP知道它是如何工作的.他们问**为什么**以这种方式实施. (3认同)
  • 他们的功能被破坏了。时期。这就是为什么他们反对并消除它。不幸的是,ISO 标准很糟糕,微软关闭 ANSI_NULL 的方法要好得多,但由于 a=b 在两者都为空时无法按预期工作的明显故障,他们被迫消除了该功能。我希望他们能修复它并保留该功能。当且仅当比较中涉及的值为空时,任何人都没有理由必须编写特殊查询来将“=”替换为“is”。多么痛苦啊。 (3认同)