Subquery

對於與外部查詢同名的不存在列,子查詢不會出錯

  • September 29, 2018

我在 MySQL 數據庫中有兩個表 -t1一個列c1t2一個列c2

我執行這個查詢:

select * from t1 where c1 in (select c1 from t2);

上面的查詢應該給出一個錯誤,因為c1t2 中沒有。相反,它從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);

上面的查詢應該給出一個錯誤,因為c1t2 中沒有。相反,它從t1.

不,查詢不應該給出錯誤。這是一個常見的錯誤(認為c1in(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);
  • whent2沒有名為 的列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

引用自:https://dba.stackexchange.com/questions/218871