在我的表中,我有一个可空的位列(遗留系统......),另一个开发人员最近对存储过程进行了更改,只显示位列不为真的值(1)。因为这是一个可以为空的列,所以我们注意到如果列为NULL,则记录未被拾取。为什么是这样?
其他开发者和我同意NULL<> 1 ...这是SQL中的错误还是这样设计的?看起来像是一个设计缺陷。
当前代码:
(VoidedIndicator <> 1)
建议修复:
(VoidedIndicator <> 1 OR VoidedIndicator IS NULL)
澄清(作者Jon Erickson)
VoidedIndicator是一个可空的位字段,因此它可以具有以下值:NULL,0或1
当使用诸如(VoidedIndicator&lt;&gt; 1)之类的where子句创建SQL语句时,我们只获得返回的具有VoidedIndicator == 0的记录,但我们期望VoidedIndicator == 0和VoidedIndicator IS为NULL。这是为什么?
答案 0 :(得分:12)
很多好的答案,但是让我给你一个非常简洁的版本。
对于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
答案 1 :(得分:11)
例如,WHERE子句或 条件语句可能会比较一个 列的值带有常量。它是 经常错误地认为a 缺失值将是“小于”或 “不等于”如果那是一个常数 字段包含Null,但事实上, 这样的表达式返回Unknown。一个 示例如下:
-- Rows where num is NULL will not be returned, -- contrary to many users' expectations. SELECT * FROM sometable WHERE num <> 1;
基本上,在NULL和其他东西之间的任何比较,无论是使用=还是&lt;&gt;不会是真的。
作为另一个参考,MSDN T-SQL page on <>
州:
比较两个表达式(比较 运营商)。当你比较nonnull 表达式,如果是,则结果为TRUE 左操作数不等于右边 操作数;否则,结果是 假。如果是其中一个或两个操作数 NULL,请参阅SET ANSI_NULLS (处理SQL)。
SET ANSI_NULLS页面然后声明:
当SET ANSI_NULLS为ON时,为SELECT 使用WHERE column_name的语句 = NULL返回零行,即使column_name中有空值也是如此。一个 使用WHERE的SELECT语句 column_name&lt;&gt; NULL返回零行 即使有非空值 列名。
...
当SET ANSI_NULLS为ON时,全部 与空值进行比较 评估为UNKNOWN。当SET ANSI_NULLS为OFF,比较所有 针对空值的数据评估为 如果数据值为NULL,则为TRUE。
答案 2 :(得分:3)
这不是一个错误。
NULL不等于任何东西,甚至不是NULL(NULL = NULL返回FALSE)。
通常,NULL值也不会被编入索引。依赖特定值或NULL通常是个坏主意。根据您在列中存储的内容,您可能最好放入虚拟或标记值,而不是使用NULL来表示某些含义。
答案 3 :(得分:1)
其他人都认为NULL <> 1
没有评估为真,因此它不符合WHERE
条款。
您描述的建议修补程序是处理它的最佳方法:
(VoidedIndicator <> 1 OR VoidedIndicator IS NULL)
在这种情况下,SQL-99确实有一个谓词,称为IS DISTINCT FROM
:
(VoidedIndicator IS DISTINCT FROM 1)
此谓词的行为与您提出的修复完全相同。遗憾的是,Microsoft SQL Server尚不支持IS DISTINCT FROM
。
答案 4 :(得分:0)
您还可以:isnull(VoidedIndicator,1)&lt;&gt; 1
答案 5 :(得分:0)
因为WHERE子句仅在条件计算结果为true时选择行。
当其中一个操作数为NULL时,条件通常计算为UNKNOWN(大约等于NULL),因此不为真。它适用于“column = 1
”和“column <> 1
”;如果column为NULL,则搜索条件失败。
这就是为什么你被告知尽可能避免使用NULL列。
答案 6 :(得分:0)
NULL&lt;&gt; 1(理论上)评估为“可能”,这意味着不会返回记录。