2017-09-07 116 views
6

Gần đây tôi đã có một tình huống mà tôi cần xóa một số hàng khỏi bảng và đánh vần sai tên cột. Không có lỗi nào bị ném và TẤT CẢ các hàng đã bị xóa khỏi bảng. Đây là tập lệnh tạo lại sự cố.WHERE IN (SELECT NonExistingColumnName) gây ra hành vi bất ngờ

Có bảng Đơn đặt hàng có bốn đơn đặt hàng với OrderID. Có một bảng LIST_TO_DELETE với một ItemID.

tôi nên đã sử dụng

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

thay vào đó tôi sử dụng

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

này gây ra tất cả các hàng trong bảng #orders bị xóa khi tôi chỉ có nghĩa là để xóa một.

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 

Trong mã ban đầu của tôi, bảng Đơn hàng là thật và LIST_TO_DELETE là biến bảng nhưng có vẻ như không có sự khác biệt về loại bảng được sử dụng. Nếu tôi sử dụng bất kỳ tên cột ngoài OrderID hoặc ItemID, tôi nhận được một lỗi

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

Tại sao mã này cư xử theo cách này?

Trả lời

4

Đọc bài viết để hiểu điều gì đang xảy ra: Qualifying Column Names in Subqueries

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.

5

Đây là sự cố đã biết.

Tuyên bố sau đây sẽ sai lầm deleteALL các hàng từ bảng người dùng:

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

ngay cả khi bảng nhóm không có một cột tên là user_id.

Tuyên bố sau đây sẽ, tuy nhiên, ném ra một lỗi:

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 

EDIT

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

này ném một lỗi, vì OtherID không tồn tại trong #Orders

+2

Tôi không tin rằng tôi đã gặp phải điều đó, nhưng dường như với tôi rằng không có bí danh, SQL Server cho rằng id người dùng đến từ bảng người dùng. một thử nghiệm dễ dàng sẽ là sử dụng một tên cột không tồn tại trong một trong hai bảng và xem những gì sẽ xảy ra. –

+0

Điều đó sẽ gây ra lỗi. Bạn đúng về SQL giả định rằng user_id đến từ bảng người dùng – Raj

+0

@Raj Bạn có liên kết đến một MSDN hay bất kỳ trang Microsoft nào mà vấn đề này được mô tả không? – Don

Các vấn đề liên quan