这是我在Microsoft Sql Server中发现的奇怪行为。如果我错了,请纠正我。
SELECT COUNT(*) FROM TABLEA
WHERE [Column1] IS NULL;
返回30018行。
CREATE VIEW VIEWB AS
SELECT * FROM TABLEA AS t1
WHERE t1.[Column1] NOT IN ('Cross/Up sell', 'Renegotiation', 'Renewal')
如果我选中VIEWB
,我在NULL
中找不到Column1
:
SELECT COUNT(*) FROM VIEWB
WHERE [Column1] IS NULL;
返回0行。
为什么呢?上面的查询排除了3个值,但不应该排除NULL 。为什么Sql Server Ms会以这种方式运行?我应该预料到这一点吗? 我该如何解决?
答案 0 :(得分:15)
这实际上是SQL Server在将NULL视为值时所犯的常见错误。默认情况下,它被视为UNKNOWN,如文档here所示。因此,在您看来,您还需要添加OR t1.[Column1] IS NULL
。
您可以通过调用SET ANSI_NULLS OFF
来更改此行为。但是,不建议使用此功能,因为@Martin Smith指出该功能已被弃用。
但这不是SQL Server特有的问题。它是ANSI SQL standard。
的一部分答案 1 :(得分:12)
SQL使用three valued logic。
t1.[Column1] NOT IN ('Cross/Up sell', 'Renegotiation', 'Renewal')
相当于
t1.[Column1] <> 'Cross/Up sell' AND
t1.[Column1] <> 'Renegotiation' AND
t1.[Column1] <> 'Renewal')
当t1.[Column1] is NULL
此表达式求值为UNKNOWN
而不是TRUE
时,不会返回这些行。
唯一的时间NULL NOT IN ( ... )
将返回NOT IN
子句评估为空集。
答案 2 :(得分:3)
最佳答案是在where子句
中使用以下条件ISNULL(t1。[Column1],'') NOT IN('Cross / Up sell','Renegotiation','Renewal')
答案 3 :(得分:1)
在处理nulls
我只是同意Sumo - 为什么不将视图更改为:
CREATE VIEW VIEWB AS
SELECT * FROM TABLEA AS t1
WHERE
t1.[Column1] NOT IN ('Cross/Up sell', 'Renegotiation', 'Renewal')
OR
t1 IS NULL
替代方案可能是我已添加到SQL FIDDLE
的以下内容CREATE VIEW VIEWB AS
SELECT * FROM TABLEA AS t1
WHERE
1 = CASE
WHEN ISNULL(t1.[Column1],'x') NOT IN ('Cross/Up sell', 'Renegotiation', 'Renewal') THEN 1
ELSE 0
END
答案 4 :(得分:0)
确认这是SQL Server 2016的最佳解决方案
WHERE ISNULL(t1。[Column1],&#39;&#39;)NOT IN(&#39; Cross / Up sell&#39;,&#39; Renegotiation&#39;,&#39; Renewal& #39)