无法自然加入工作

时间:2016-11-06 16:08:05

标签: sql database postgresql natural-join

我使用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);

我想自然地加入Book and Publisher并获得由牛津大学出版社出版的书籍。

这有效:

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;

为什么?

2 个答案:

答案 0 :(得分: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无论如何都不会在我的数据库中运行。

答案 1 :(得分: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:

  

NATURAL是USING的简写形式:它形成一个USING列表,其中包含出现在两个输入表中的所有列名。与USING一样,这些列在输出表中只出现一次。如果没有常用的列名,则NATURAL的行为类似于CROSS JOIN。