在我的表中,我有一个可空的位列(遗留系统......),另一个开发人员最近对存储过程进行了更改,只显示位列不为真的值(1).因为这是一个可以为空的列,所以我们注意到如果列为NULL,则记录未被拾取.为什么是这样?
其他开发人员和我同意NULL <> 1 ...这是SQL中的错误还是这样设计的?看起来像一个设计缺陷.
现行代码:
(VoidedIndicator <> 1)
建议修复:
(VoidedIndicator <> 1 OR VoidedIndicator IS NULL)
澄清(作者Jon Erickson)
VoidedIndicator是一个可空的位字段,因此它可以具有以下值:NULL,0或1
当使用诸如(VoidedIndicator <> 1)之类的where子句创建SQL语句时,我们只获得返回的具有VoidedIndicator == 0的记录,但我们期望VoidedIndicator == 0和VoidedIndicator IS NULL.为什么是这样?
很多好的答案,但让我给你一个非常简洁的版本.
对于SQL,Null并不意味着"没有价值"意味着"未知价值"
考虑到这一点,请考虑您用简单的英语问SQL的问题的答案.
Q: Is this unknown value not equal to 1? A: I don't know, there is no way to tell without knowing the value. Hence Null<>1 = Null
从关于NULL的Wikipedia条目:
例如,WHERE子句或条件语句可能会将列的值与常量进行比较.如果该字段包含Null,则通常错误地认为缺失值将"小于"或"不等于"常量,但实际上,此类表达式返回Unknown.一个例子如下:
-- Rows where num is NULL will not be returned, -- contrary to many users' expectations. SELECT * FROM sometable WHERE num <> 1;
基本上,NULL和其他东西之间的任何比较,无论是否带有=或<>都不会成立.
作为另一个参考,关于<>
状态的MSDN T-SQL页面:
比较两个表达式(比较运算符).比较非空表达式时,如果左操作数不等于右操作数,则结果为TRUE; 否则,结果为FALSE.如果其中一个或两个操作数均为NULL,请参阅SET ANSI_NULLS(Transact-SQL).
该SET ANSI_NULLS然后页指出:
当SET ANSI_NULLS为ON时,即使column_name中存在空值,使用WHERE column_name = NULL的SELECT语句也会返回零行.使用WHERE column_name <> NULL的SELECT语句返回零行,即使column_name中存在非空值也是如此.
...
当SET ANSI_NULLS为ON时,对空值的所有比较都计算为UNKNOWN.当SET ANSI_NULLS为OFF时,如果数据值为NULL,则将所有数据与空值的比较计算为TRUE.