Query
在混合新舊連接語法時查詢邏輯處理階段
FROM
如果我混合使用新舊語法來連接表,誰能澄清為什麼表的順序很重要?例如,SELECT * FROM table1 a, table2 b INNER JOIN table3 c ON (c.a_id = a.id) -- error - a.id - invalid identifier WHERE (a.id = b.a_id) SELECT * FROM table2 b, table1 a INNER JOIN table3 c ON (c.a_id = a.id) -- ok, table1 a is the last in FROM WHERE (a.id = b.a_id)
我不會使用這種醜陋的查詢,但我相信在查詢中指定的所有表都
FROM
應該對查詢的其他部分可見。我不認為這取決於 RDMS,因為 SQLServer、Oracle 和 Mysql 的行為方式相同 - 第一次查詢出錯,第二次沒有錯誤。我肯定遺漏了一些明顯的東西,但我沒有找到任何描述它為什麼會這樣工作的東西。
謝謝你。
這與逗號運算符的優先級有關。如MySQL 文件中所述
逗號運算符的優先級小於
INNER JOIN
,CROSS JOIN
,LEFT JOIN
, 等等。如果在存在連接條件時將逗號連接與其他連接類型混合使用,則會出現表單錯誤Unknown column 'col_name' in 'on clause' may occur
您通過下面的重寫得到相同的結果(其中
ON
子句的位置清楚地表明了連接操作的邏輯順序)失敗
SELECT * FROM table1 a INNER JOIN (table2 b INNER JOIN table3 c ON c.a_id = a.id ) -- error - a.id - invalid identifier ON a.id = b.a_id
成功
SELECT * FROM table2 b INNER JOIN (table1 a INNER JOIN table3 c ON c.a_id = a.id ) ON a.id = b.a_id
在成功的那個
a
首先加入到c
,c.a_id = a.id
然後由該加入產生的虛擬表加入到所有工作正常的虛擬表b
上。a.id = b.a_id
對於第
b
一次嘗試連接失敗的c
那個c.a_id = a.id
,因為引用 table 是無效的a
。該ON
子句只能引用它之前的表或前一個ON
子句已經引入的表。根據條件
c.a_id = a.id
,a.id = b.a_id
然後c.a_id=b.a_id
您可以將連接條件更改為該條件,它會起作用,或者您當然也可以使用派生表或視圖來更改優先級並確保a,b
在加入之前被視為邏輯連接單元c
SELECT * FROM (SELECT * FROM table2 b, table1 a) ba INNER JOIN table3 c ON ( c.a_id = ba.id ) WHERE ( ba.id = ba.a_id )