WHERE IN (SELECT NonExistingColumnName) 导致意外行为

2021-09-10 00:00:00 tsql sql-server-2008 sql-server

我最近遇到了一种情况,我需要从表中删除一些行并拼错列名.没有抛出错误,所有行都从表中删除.这是重现该问题的脚本.

I recently had a situation where I needed to delete some rows from a table and mis-spelt a column name. There was no error thrown and ALL the rows were deleted from the table. Here is a script that reproduces the issue.

有一个 Order 表,有四个带有 OrderID 的订单.有一个带有一个 ItemID 的 LIST_TO_DELETE 表.

There is an Order table with four orders with OrderID. There is a LIST_TO_DELETE table with one ItemID.

我应该用过

DELETE TOP(1) FROM #Orders WHERE OrderID IN (SELECT ItemID FROM #LIST_TO_DELETE  )

我用了

DELETE TOP(1) FROM #Orders WHERE OrderID IN (SELECT OrderID FROM #LIST_TO_DELETE  )

这导致 #Orders 表中的所有行都被删除,而我只想删除一个.

This caused all rows in the #Orders table to be deleted when I only meant to delete one.

CREATE TABLE #Orders (OrderID INT, OrderName VARCHAR(100))
INSERT INTO #Orders(OrderID, OrderName) VALUES (1,'Order One'),(2,'Order Two'),(3,'Order Three'), (4,'Order Four')

CREATE TABLE #LIST_TO_DELETE (ItemID INT);INSERT INTO #LIST_TO_DELETE(ItemID) VALUES (1)

DECLARE @rowcount INT = 1
WHILE @rowcount > 0 
BEGIN
    DELETE TOP(1) FROM #Orders WHERE OrderID IN (SELECT OrderID FROM #LIST_TO_DELETE  )
    SET @rowcount = @@rowcount
END 

SELECT * FROM #Orders

DROP TABLE #Orders
DROP TABLE #LIST_TO_DELETE

在我的原始代码中,Orders 表是真实的,而 LIST_TO_DELETE 是一个表变量,但使用什么表类型似乎没有区别.如果我使用除 OrderID 或 ItemID 之外的任何列名,我会收到错误

In my original code, the Orders table was real and LIST_TO_DELETE was a table variable but it seems to make no difference what table type is used. If I use any column name apart from OrderID or ItemID, I get an error

DELETE TOP(1) FROM #Orders WHERE OrderID IN (SELECT OtherID FROM #LIST_TO_DELETE  )
 Invalid column name 'OtherID'

为什么这段代码会这样?

Why did this code behave this way?

推荐答案

阅读文章以了解正在发生的事情:在子查询中限定列名

Read the article to understand what is happening: Qualifying Column Names in Subqueries

一般规则是语句中的列名由同一级别的 FROM 子句中引用的表隐式限定.如果子查询的 FROM 子句中引用的表中不存在列,则该列由外部查询的 FROM 子句中引用的表隐式限定.

The general rule is that column names in a statement are implicitly qualified by the table referenced in the FROM clause at the same level. If a column does not exist in the table referenced in the FROM clause of a subquery, it is implicitly qualified by the table referenced in the FROM clause of the outer query.

相关文章