INERE(SELECT NonExistingColumnName)导致意外行为

时间:2017-09-07 08:03:31

标签: sql-server sql-server-2008 tsql

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

有一个订单表,其中包含四个OrderID订单。 有一个带有一个ItemID的LIST_TO_DELETE表。

我应该用

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表中的所有行都被删除,而我只想删除一行。

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之外的任何列名,我会收到错误

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

为什么这段代码会这样?

2 个答案:

答案 0 :(得分:5)

这是一个已知问题。

以下语句将错误地delete 所有来自users表中的行:

DELETE FROM users WHERE user_id IN (SELECT user_id FROM groups);

即使groups表没有名为user_id的列。

但是,以下语句将引发错误:

DELETE FROM users WHERE user_id IN (SELECT g.user_id FROM groups g);

Msg 207, Level 16, State 1, Line 1
Invalid column name user_id

修改

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

这会引发错误,因为OtherID中不存在#Orders

答案 1 :(得分:4)

阅读文章以了解正在发生的事情:Qualifying Column Names in Subqueries

  

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