使用IN子句的子查询有什么危险?

时间:2015-07-09 16:37:18

标签: sql sql-server where-clause in-clause

我最近发现了一个查询(后来已经丢失),这个问题似乎与使用子查询和IN子句有关。例如:

SELECT * FROM Table1 WHERE Column1 IN (SELECT Column1 FROM Table2)

我似乎注意到的问题是,当我使用IN和NOT IN时,每个数字都没有考虑表1中的总记录。虽然Table1在Column1中没有任何NULL值,但我相信Table2确实如此。这会引起一个问题吗?我很欣赏通过标准逻辑运算符将某些内容与NULL进行比较在T-SQL中不起作用,但我无法找到有关子子查询的IN子句的任何内容。

我很遗憾没有原始查询,当我尝试使用一些非常通用的代码重现问题时,我做不到。所以我很欣赏这可能是一个模糊的问题,但了解任何危险是很有用的。当使用带有子查询的IN / NOT IN运算符时,人们可能通常不会意识到,特别是与NULLS有关。任何其他与NULLS无关的一般危险也是有用的。

我认为一般的建议是使用JOIN,但这主要是为了能够识别现有代码中的可能问题并在必要时进行修复。

1 个答案:

答案 0 :(得分:0)

以下查询:

SELECT *
FROM Table1
WHERE Column1 NOT IN (SELECT Column1 FROM Table2)

如果 Table2.Column1永远是NULL,则永远不会返回行。为什么?好吧,如果Column1Table2中的值匹配,则表达式返回false。如果Column1与某个值不匹配,那么您可以与NULL进行比较 - 该比较会返回NULL

我的建议是改为使用NOT EXISTS

SELECT t1.*
FROM Table1 t1
WHERE NOT EXISTS (SELECT Column1 FROM Table2 t2 WHERE t2.Column1 = t1.Column1)

这有更多预期的行为。

可以使用JOIN,但这会产生重复行的风险。