2012-10-11 34 views
5

我有一塊SQL(你會認爲)不會編譯,而是刪除目標表中的所有行。SQL刪除清除表而不是錯誤

考慮此設置:

create table TableA (ColumnA varchar(200)); 
create table TableB (ColumnB varchar(200)); 

insert TableA values ('A'),('B'),('C'); 
insert TableB values ('A'); 

然後下面的SQL:

--Returns all rows from TableA 
select * from TableA; 

--Does not error (ColumnA does not exist on TableB) 
delete TableA where ColumnA in (select ColumnA from TableB) 

--No Rows are returned 
select * from TableA; 

DELETE語句以上會導致所有行從TableA被刪除,而不是示數是ColumnA不存在TableB

有一個SQL小提琴在這裏惡化這個:http://www.sqlfiddle.com/#!3/9d883/6

看起來TableAColumnA正在被拿起,但預計它會「超出範圍」。

這是爲什麼?

回答

4

由於內部查詢中的ColumnA與外部的查詢之間的相關性,它可以按預期工作。

這種常用的相關查詢模式是有效的

DELETE TableA WHERE NOT EXISTS (select * from TableB where TableB.ID=TableA.ID) 

它刪除沒有在表B依賴記錄表A項。

它顯示您可以引用相關查詢中的TableA列。在您的查詢

delete TableA where ColumnA in (select ColumnA from TableB) 

內查詢生產

  • 一行TableB中每個記錄的每一行,其值ColumnA從外部查詢
  • 一列

所以DELETE通過

3

雖然我理解這種混亂,它表現爲這應該。 ColumnA仍然在「範圍內」。事實上,如果你願意,你可以在你的子查詢中加入它。括號不限制範圍,但從可讀性的角度來看,我可以看到它造成的混亂。

這是爲什麼始終在表名(或別名)前添加列名是個好主意的另一個例子。

+2

絕對不要在你的列名前加上表名,那個人會是一些醜陋的模式,但絕對使用別名... – emalamisura