如果“IN”子查询失败,SQL将返回所有行

时间:2015-08-03 13:42:12

标签: sql sql-server tsql stored-procedures

所以最近我通过快速编码而不是很好地测试我的代码,并且发布存储过程时出现了编译器无法捕获的错误,从而给自己带来了很多麻烦。我有这样的查询:

--Lets say I have a table SomeTable (SomeId, CreateDate, UpdatedDate)

DECLARE @Temp TABLE (Id INT);

INSERT INTO @Temp (Id)
SELECT SomeId FROM SomeTable WHERE CreateDate > SomeDate;

UPDATE SomeTable 
SET UpdatedDate = GETDATE()
WHERE SomeId IN (SELECT TempId FROM @Temp);

现在编译器没有发现我试图在我的子查询中选择一个在我的临时表中不存在的列(我得到的)。但是,在我看来,如果子查询在这种情况下失败,则不应该返回任何行。当我在SomeTable中运行这个每一行时都更新了。你可以想象,这是一个巨大的痛苦。有没有人知道为什么这样做?我似乎无法在网上找到答案。

1 个答案:

答案 0 :(得分:4)

你认为你写了这个查询:

UPDATE SomeTable  s
SET UpdatedDate = GETDATE()
WHERE s.SomeId IN (SELECT t.TempId FROM @Temp t);

但是,如果t.TempId不存在,那么SQL Server(以及所有其他数据库)将其解释为:

UPDATE SomeTable  s
SET UpdatedDate = GETDATE()
WHERE s.SomeId IN (SELECT s.TempId FROM @Temp t);

如果您要获取所有行,则列SomeTable.TempId的值与SomeTable.SomeId的值相同。我的猜测是你在两个地方使用了相同的列名。因此,您的查询基本上是SomeTable.SomeId = SomeId - 只要SomeId不是NULL,就是如此。

如果您遵循始终使用表别名限定列名称的投注练习,那么您就不会遇到此问题。如果您已经这样做了,那么查询的第一个版本就会失败,可能会出现可理解的错误。