2016-11-06 51 views
3

我正在使用postgresql,但我也在sqlfiddle.com中確認了這一點。無法自然加入工作

我的表和要素是:

create table Publisher(pID int PRIMARY KEY, name varchar(255), address varchar(255)); 
create table Book(ISBN int PRIMARY KEY, name varchar(255), genre varchar(255), price int, copies int, pID int REFERENCES Publisher(pID)); 
insert into Publisher values(1, 'Oxford University Press', 'Senkosova'); 
insert into Book values(111, 'Alamut', 'Horror', 50, 100, 1); 

我想自然連接圖書和出版,並得到這是由牛津大學出版社出版的圖書。

這工作:

select b.name 
from Book as b, Publisher as p 
where b.pid = p.pid and p.name ='Oxford University Press'; 

這不:

select b.name 
from Book as b natural join Publisher as p 
where p.name = 'Oxford University Press'; 

即使這並不:

select * 
from Book natural join Publisher; 

爲什麼?

回答

3

不要使用natural join,這是一個等待發生的錯誤。相反,使用顯式onusing條款:

select b.name 
from Book b join 
    Publisher p 
    using (pid) 
where p.name = 'Oxford University Press'; 

或:

select b.name 
from Book b join 
    Publisher p 
    where b.pid = p.pid 
where p.name = 'Oxford University Press'; 

的問題natural join是雙重的。首先,它將用於比較的列基於公用的名稱,甚至不在已聲明的外鍵關係上。無論你的表有name柱以及一個id列,因此在最低限度,自然連接查詢等效於:

select b.name 
from Book b join 
    Publisher p 
    where b.pid = p.pid and b.name = p.name 
where p.name = 'Oxford University Press'; 

(也有可能是具有相同的名稱等欄目。)我懷疑任何書籍都被命名爲「牛津大學出版社」,所以你在數據中沒有匹配。

第二個問題是相關的。通過不明確包含用於加入的列,查詢的讀者不知道。這使得查詢更難以調試和理解。在我的情況下,我創建的幾乎所有表格都有CreatedAtCreatedBy列,所以natural join在我的數據庫中永遠不會工作。

+0

謝謝您的全面解答! – TugRulz

3

在兩個表中,您都有多個具有相同名稱的列:idname。所以

select * 
from book 
natural join publisher; 

相當於

select * 
from book b 
join publisher p on b.pid = p.pid 
and b.name = p.name; 

the documentation:

自然科學使用的簡寫形式:它形成了由該出現在兩個輸入表中的所有列名的使用列表。和USING一樣,這些列在輸出表中只出現一次。如果沒有公共列名稱,那麼NATURAL的行爲就像CROSS JOIN。

+0

謝謝。我現在明白了。 – TugRulz