奇怪的SQL行为,我想知道为什么它的工作方式

时间:2010-03-25 20:32:12

标签: sql sql-server-2005 tsql

考虑以下Transact sql。

DECLARE @table TABLE(val VARCHAR(255) NULL)

INSERT INTO @table (val) VALUES('a')
INSERT INTO @table (val) VALUES('b')
INSERT INTO @table (val) VALUES('c')
INSERT INTO @table (val) VALUES('d')
INSERT INTO @table (val) VALUES(NULL)

select val 
from @table
where val not in ('a') 

我希望这会回来

b, c, d, NULL

但它会返回

b, c, d

为什么会这样?是否未评估NULL?在某个'a'中是否为NULL?

5 个答案:

答案 0 :(得分:3)

获取空行尝试:

select val 
from @table
where val not in ('a') OR val IS NULL

试试这些:

select 1 where null in (null)
select 1 where null in (1)
select 1 where 1 in (null)

全部返回零行

null = null始终为false null = anythng始终为false ,在测试NULL行时,WHERE子句在('a')中为WHERE NULL,因此它总是错误的。

答案 1 :(得分:3)

答案

默认情况下,NULL表示SQL,表示“未知”。因此,与“未知”的任何比较都是“未知”。

例如,如果一个陌生人站在鲍勃旁边,你想问一个问题,“陌生人的名字和鲍勃的名字一样吗?”。答案是未知的。

因为您要求“返回任何值不是'A'的记录”。当它到达那个NULL列时,SQL仍然说,“我不知道”。由于表达式的计算结果为true,因此不会返回该记录。

解决方案

将NULL与常量进行比较的任何表达式始终为NULL,因此请使用特殊IS NULLIS NOT NULL来测试NULL值。

这会让您bcdNULL

SELECT val 
FROM @table
WHERE val NOT IN ('a') OR val IS NULL

解决方法

您可以更改NULL的默认行为:

SET ANSI_NULLS OFF

答案 2 :(得分:2)

Null不能直接与任何东西进行比较。

select val  
from @table 
where coalesce(val, '') not in ('a')  

答案 3 :(得分:2)

试试这个,你会得到一个不同的答案:

set ansi_nulls off;
DECLARE @table TABLE(val VARCHAR(255) NULL)

INSERT INTO @table (val) VALUES('a')
INSERT INTO @table (val) VALUES('b')
INSERT INTO @table (val) VALUES('c')
INSERT INTO @table (val) VALUES('d')
INSERT INTO @table (val) VALUES(NULL)

select val 
from @table
where val not in ('a')

你有ansi_nulls,因此它会相应地处理空值。

答案 4 :(得分:2)

以这种方式不能与NULL相等。

考虑一下

select case when 'a' = NULL then 1 else 0 end
select case when 'a' <> NULL then 1 else 0 end

上面你会得到

result
------
  0
  0

对于您的查询,请尝试

 where isnull(val,'') not in ('a')