3 votes

Je n'arrive pas à faire fonctionner le joint naturel

J'utilise postgresql, bien que j'ai confirmé cela dans sqlfiddle.com aussi.

Mes tables et éléments sont :

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);

Je veux rejoindre naturellement Book and Publisher et obtenir les livres qui sont publiés par Oxford University Press.

Ça marche :

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

Ce n'est pas le cas :

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

Même cela ne le fait pas :

select *
from Book natural join Publisher;

Pourquoi ?

3voto

Gordon Linoff Points 213350

Ne pas utiliser natural join c'est un bug qui attend de se produire. Au lieu de cela, utilisez un on o using clause :

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

ou :

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

Le problème avec natural join est double. Tout d'abord, elle fonde les colonnes de comparaison sur des noms même pas sur les relations de clés étrangères déclarées. Vos deux tables ont une name ainsi qu'une colonne id donc au minimum, la requête de jointure naturelle est équivalente à :

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';

(Je doute qu'il y ait des livres nommés "Oxford University Press", donc vous n'avez aucune correspondance dans les données.

Le deuxième problème est lié. En n'incluant pas explicitement les colonnes utilisées pour la jointure, un lecteur de la requête ne le sait pas. Cela rend la requête plus difficile à déboguer et à comprendre. Dans mon cas, presque toutes les tables que je crée ont CreatedAt y CreatedBy colonnes, donc natural join ne fonctionneraient jamais dans mes bases de données de toute façon.

3voto

klin Points 52538

Vous avez plus d'une paire de colonnes portant le même nom dans les deux tables : id y name . Donc

select *
from book 
natural join publisher;

est équivalent à

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

Par la documentation :

NATURAL est une forme abrégée de USING : elle forme une liste USING composée de tous les noms de colonnes qui apparaissent dans les deux tables d'entrée. Comme avec USING, ces colonnes n'apparaissent qu'une seule fois dans la table de sortie. S'il n'y a pas de noms de colonnes communs, NATURAL se comporte comme CROSS JOIN.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X