zea*_*eal 5 null sql-server uniqueidentifier subquery
当我有一个查询来检查uniqueidentifer
具有空值的表中是否不存在类型的列时,我不会得到任何结果。如果子查询不返回空值,则它工作正常,并且仅在使用not in
.
我知道我可以只not null
检查我的子查询,但我很好奇为什么这不起作用。
查询示例:
select a.guid from tableA a where a.guid not in (select b.guid from tableB AS b)
Run Code Online (Sandbox Code Playgroud)
工作测试:
select 1 where newid() not in (select newid())
Run Code Online (Sandbox Code Playgroud)
破碎测试:
select 1 where newid() not in (select null)
Run Code Online (Sandbox Code Playgroud)
Mar*_*ith 11
只是为了对billinkc 的回答提供一些额外的解释。
如果 null 是一张王牌,您可能想知道为什么不WHERE 2 IN (2,3, NULL)
表现出相同的行为?
那个按预期工作,因为它评估为(2=2) OR (2=3) OR (2=NULL)
.
根据三个值逻辑 for Or
-ed 条件的规则,如果它们中的任何一个评估为true
表达式 is true
。否则,如果它们中的任何一个评估为unknown
表达式 is unknown
。唯一的另一种可能性是,false
在这种情况下,表达式的计算结果为false
。
为了在 SQL 中返回一行,WHERE
子句必须计算为true
而不是false
or unknown
。以上就是这样做的。
该表达式的1 NOT IN (2,3, NULL)
计算结果为(1 <> 2) AND (1 <> 3) AND (1 <> NULL)
。当条件为AND
-ed 时,所有条件都必须计算为true
,以便表达式计算为true
。
NULL
列表中的的存在保证了至少会有一个UNKNOWN
并且永远不会是这种情况。因此,在这种情况下,“ NULL 全部”行为的原因。
在这里打个比方,说明为什么这种NOT IN
行为是有意义的。
汤姆、迪克和哈利的三个朋友和一个完全陌生的人坐在火车车厢里,他们的名字不为他们所知。
如果有人问汤姆“你的名字和这辆马车上其他人的名字不同吗?” 那么他就不可能有把握地回答了。
即使他知道这一点
Tom <> Dick
并且Tom <> Harry
(因此该陈述可能是真实的)该陈述的整体真实性取决于陌生人的姓名,而这是未知的。这类似于 SQL
'Tom' NOT IN ('Dick', 'Harry', Null)
用一个例子来吹嘘我的评论。无论您使用的是 GUID 还是任何其他数据类型,这都无关紧要。您的过滤器应评估为真或假条件。在 .net/python/java/etc 这就是你得到的。在 SQL 世界中,我们可以将三态内置于所有内容中。是真的,是假的,是……我不知道。
当 NULL 值进入混合时,它就是一张王牌。它会崩溃任何其他值,无论是真还是假,并说“很难,这现在是未知的”。由于它无法给出权威答案,因此它不会提供答案。无论您是否认为这是一个破碎的设计,它只是。
-- NULL pooches it all
SELECT 1 AS query1 WHERE 1 NOT IN (SELECT NULL);
-- No null, no problem
SELECT 2 AS query2 WHERE 1 NOT IN (2,3,4);
-- Null, we meet again. With the same result
SELECT 3 AS query3 WHERE 1 NOT IN (2,3,4, NULL);
Run Code Online (Sandbox Code Playgroud)
忽略关于 NULL 的教训(你应该观察),NOT IN
即使没有涉及 NULL ,对于左反半连接也可能是一个可怕的选择。看看NOT IN
与以下相比,您是否可以获得更好的性能或更好的计划NOT EXISTS
:
select a.guid
from dbo.tableA AS a
where not exists
(
select 1
from tableB AS b
where b.guid = a.guid
);
Run Code Online (Sandbox Code Playgroud)