Oracle

為什麼這個查詢有效?

  • June 27, 2016

我有兩個表,table_a (id, name) 和 table_b (id),假設在 Oracle 12c 上。

為什麼這個查詢不返回異常?

select * from table_a where name in (select name from table_b);

據我了解,甲骨文認為這是

select * from table_a where name = name;

但我不明白為什麼?

即使table_b沒有name列,查詢也是語法正確的 SQL。原因是范圍解析。

解析查詢時,首先檢查是否table_bname列。既然沒有,那就table_a檢查一下。只有當兩個表都沒有列時,它才會拋出錯誤name

最後查詢執行如下:

select a.* 
from table_a  a
where a.name in (select a.name 
                from table_b  b
               );

至於查詢將給出的結果,對於 的每一行table_a,子查詢(select name from table_b)- 或(select a.name from table_b b)- 是一個表,其中包含具有相同值的單列a.name和與 一樣多的行table_b。因此,如果table_b有 1 行或更多行,則查詢執行如下:

select a.* 
from table_a  a
where a.name in (a.name, a.name, ..., a.name) ;

要麼:

select a.* 
from table_a  a
where a.name = a.name ;

要麼:

select a.* 
from table_a  a
where a.name is not null ;

如果table_b為空,則查詢將不返回任何行(感謝@ughai 指出這種可能性)。


這(您沒有收到錯誤的事實)可能是所有列引用都應以表名/別名為前綴的最佳原因。如果查詢是:

select a.* from table_a where a.name in (select b.name from table_b); 

你會馬上得到錯誤。當表前綴被省略時,這樣的錯誤並不難發生,尤其是在更複雜的查詢中,更重要的是,不會被注意到。

另請閱讀Oracle 文件:靜態 SQL 語句中的名稱解析,內部擷取中的類似範例 B-6以及避免 SELECT 和 DML 語句中的內部擷取段落中的建議:

使用適當的表別名限定語句中的每個列引用。

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