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 TRUENULL
表示我不知道,这是一个缺勤值
在您的情况下,
中的将转换为
@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#中类似。