Sql not in与具有空值的in之间的差异

Sql not in与具有空值的in之间的差异,sql,sql-server,tsql,null,Sql,Sql Server,Tsql,Null,我在数据库中偶然发现了一些行为不符合预期的旧代码。我设法将它缩小到子句中的值的NULL效果 我推导了一个测试来证明这一点: declare@test nvarchar(50)='8620M/9010'; 声明@testLT nvarchar(50)='8004/9010'; 声明@testLV nvarchar(50)=null;--'asd' 当@test不在(@testLT,@testLV)时选择case,然后选择1,否则0结束 如果testLV为null,notin返回与子句中的相同的结

我在数据库中偶然发现了一些行为不符合预期的旧代码。我设法将它缩小到
子句中
值的
NULL
效果

我推导了一个测试来证明这一点:

declare@test nvarchar(50)='8620M/9010';
声明@testLT nvarchar(50)='8004/9010';
声明@testLV nvarchar(50)=null;--'asd'
当@test不在(@testLT,@testLV)时选择case,然后选择1,否则0结束
如果testLV为null,
notin
返回与
子句中的
相同的结果

我想了解这种行为背后的机制。有人能解释一下吗

注:我可能会将其替换为
,除了
条款

谨慎

比较的子查询或表达式返回的任何空值 使用IN或NOT IN返回测试_表达式未知。使用null 中的值与中的值或不在一起可能会产生意外的结果


UNKNOWN TRUE

NULL
表示我不知道,这是一个缺勤值

在您的情况下,
中的
将转换为

@test = @testLT or @test =@testLV
@test <> @testLT or @test <> @testLV
在您的情况下,
不在
将转换为

@test = @testLT or @test =@testLV
@test <> @testLT or @test <> @testLV
@test@testLT或@test@testLV

但是
NULL
不能使用
=
来获取值,当
ANSI_NULLS
设置
ON

时,列表中的
NOT IN
值会影响
的语义。在SQL中,
NULL
表示“我不知道该值;它可以是任何值。”

因此,如果你这样做:

where 1 in (1, 2)
然后它返回true

where 1 in (3, 4)
返回false

where 1 not in (3, 4, NULL)
到目前为止,一切顺利。现在考虑:

where 1 not in (1, 2, NULL)
“1”显然在清单上。所以这个返回false

where 1 not in (3, 4, NULL)
“1”不是“3”或“4”。但它是否为空?我们不知道。因此,它返回的是
NULL
,而不是true。而
NULL
WHERE
条件中被视为false,这意味着该行被过滤掉。(请注意:
检查
条件的行为不同,只有显式的false未通过
检查

因此,如果任何值为
NULL
,则
NOT IN
不会返回任何内容

这种情况几乎总是在子查询(而不是常量)的上下文中出现。因此,我建议在子查询的所有情况下使用
notexists
而不是
notin

来自:

谨慎

子查询或表达式返回的与test_表达式相比较的任何空值 在返回中使用或不使用未知。将null值与in或NOT in一起使用可能会产生意外的结果


@test和@testLV之间的比较将始终返回“UNKNOWN”,而不是TRUE或FALSE。

@test=@testLT和@test=@testLV
您的意思是这里的
还是
但是NULL不能使用or=来获取值。
ANSI_NULLS OFF?@TaPaKaHUA感谢您提醒我这是我的错误。因为
ANSI_NULLS
通常是
打开的,所以我忘了它。如果你不知道它是什么,你怎么能说它在其他东西里面还是不在其他东西里面?如果预先结束,您将得到预期的结果。
因此,这将返回NULL而不是true。在WHERE条件下,NULL被视为false。
三值逻辑:True、false、Unknown,这三值逻辑是我提出问题的原因,我假设比较的工作原理与C#中类似。