查找已删除的行:不是EXISTS与非IN

时间:2017-03-15 02:43:50

标签: sql sql-server tsql

就我而言,我有两张具有相同结构的表:TableA& TableB,我试图做的是查找A中是否存在任何记录,但不存在B.

我的脚本是

SELECT * FROM TableA
WHERE NOT EXISTS (
    SELECT * FROM TableB
)

虽然有2条记录仅存在于A但不存在于B中,但此脚本不返回任何内容。然后我改为:

SELECT ID FROM TableA
WHERE ID NOT IN (
    SELECT ID FROM TableB
)

此脚本成功运行并返回2条记录的ID。

我的问题是:这种行为是否正常? NOT EXISTSNOT IN背后的机制是什么?

我已阅读其他一些比较NOT EXISTSNOT IN的帖子,大多数人建议在99.9%的情景中使用NOT EXISTS,这种情况属于0.1%{{1}不适用? (我认为这是由于我的错误使用,如果是这样,请纠正我)

2 个答案:

答案 0 :(得分:3)

如果要查看行中的所有值,请使用EXCEPT

SELECT *
FROM TableA
EXCEPT
SELECT *
FROM TableB;

如果要正确使用NOT EXISTS,则需要一个关联子句:

SELECT a.*
FROM TableA a
WHERE NOT EXISTS (SELECT 1 FROM TableB b WHERE b.id = a.id);

我强烈建议在NOT EXISTS上使用NOT IN子查询。如果NOT IN b.id,则NULL将完全不返回任何行。这通常不是预期的。 NOT EXISTS匹配预期的语义。

答案 1 :(得分:1)

您需要小心NOT IN表达式。 A NOT IN(B,C,D)表达式基本上代表(A<>B AND A<>C AND A<>D)。如果任何值为NULL,则整个表达式将变为NULL。

因此,适用于您的示例应该是正确的NOT IN表达式(除非ID不是可空列):

SELECT ID FROM TableA
WHERE ID NOT IN (
    SELECT ID FROM TableB WHERE ID IS NOT NULL
)