Subquery
對於與外部查詢同名的不存在列,子查詢不會出錯
我在 MySQL 數據庫中有兩個表 -
t1
一個列c1
,t2
一個列c2
。我執行這個查詢:
select * from t1 where c1 in (select c1 from t2);
上面的查詢應該給出一個錯誤,因為
c1
t2 中沒有。相反,它從t1
. 上述查詢的另一個版本delete
可能更具災難性:delete from t1 where c1 in (select c1 from t2);
上面的查詢在應該給出錯誤時從 t1 中刪除所有行。
我注意到只有當子查詢中的列與外部列同名時才會發生這種行為。意義,
select * from t1 where c1 in (select c3 from t2);
將按預期拋出錯誤:
ERROR 1054 (42S22): Unknown column 'c3' in 'field list'
順便說一句,我在 PostgreSQL 9.6.3 上檢查了相同的問題,並且行為完全相同。這種奇怪的行為有什麼解釋嗎?
我執行這個查詢:
select * from t1 where c1 in (select c1 from t2);
上面的查詢應該給出一個錯誤,因為
c1
t2 中沒有。相反,它從t1
.不,查詢不應該給出錯誤。這是一個常見的錯誤(認為
c1
in(select c1 from t2)
指的是t2
。它不是由於範圍解析,即如何解析列名(如何找到它們所指的表)。查詢:select * from t1 where c1 in (select c1 from t2);
可以解決三個不同的選項:
- 當
t2
有一個名為 的列時c1
,它執行為:select * from t1 where c1 in (select t2.c1 from t2);
- when
t2
沒有名為 的列c1
,但t1
有,它執行為:(這是你的情況!)
select * from t1 where c1 in (select t1.c1 from t2);
- 當既沒有
t2
也沒有t1
名為 的列時c1
,它將引發錯誤:select * from t1 where c1 in (select c1 from t2);
– 拋出錯誤(“未知列 c1”或類似的東西)
上述查詢的另一個版本
delete
可能更具災難性:delete from t1 where c1 in (select c1 from t2);
上面的查詢在應該給出錯誤時從 t1 中刪除所有行。
出於同樣的原因,沒有。查詢解析為並執行為:
delete from t1 where c1 in (select t1.c1 from t2);
t1
所以只要t2
表不為空,它就會刪除所有行。如何避免這些問題?
始終為其表名作為列引用的前綴。通過這樣做,您將始終獲得所需的結果,或者如果該列未出現在您為其添加前綴的表中,則會出現錯誤。
您的查詢應該是:
select t1.* from t1 where t1.c1 in (select t2.c1 from t2); delete from t1 where t1.c1 in (select t2.c1 from t2);
c1
如果table中沒有列,它們都會拋出錯誤t2
。