23

这是关于我在 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我找不到:NULLColumn1

SELECT COUNT(*) FROM VIEWB 
WHERE [Column1] IS NULL;

这将返回 0 行。

为什么?上面的查询排除了 3 个值,但不应该排除 NULL。为什么 Sql Server 女士会这样?我应该预料到这一点吗?我该如何解决?

4

4 回答 4

29

这实际上是 SQL Server 在将 NULL 视为值时所犯的常见错误。默认情况下,它被视为 UNKNOWN,如此所述。因此,在您看来,您还需要包含一个OR t1.[Column1] IS NULL.

您可以通过调用来更改此行为SET ANSI_NULLS OFF。但是,不建议使用此功能,因为正如@Martin Smith 所指出的那样,该功能已被弃用。

但是,这不是 SQL Server 特定的问题。它是ANSI SQL 标准的一部分。

于 2012-07-15T12:26:40.330 回答
13

SQL 使用三值逻辑

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子句计算结果为空集。

于 2012-07-15T12:25:36.570 回答
6

最好的答案就是在 where 子句中使用以下条件

ISNULL(t1.[Column1],'') NOT IN ('Cross/Up sell', 'Renegotiation', 'Renewal')

于 2016-08-02T13:59:44.397 回答
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
于 2012-07-15T17:02:26.683 回答