90 votes

Une clé étrangère peut-elle faire référence à une clé primaire dans la même table ?

Je pense juste que la réponse est fausse parce que la clé étrangère n'a pas uniqueness propriété.

Mais certaines personnes ont dit qu'il peut être dans le cas de l'auto-jointure de la table. Je suis nouveau dans SQL . Si c'est vrai, veuillez expliquer comment et pourquoi ?

Employee table
| e_id | e_name  | e_sala  |  d_id  |
|----  |-------  |-----    |--------|
|  1   |   Tom   |  50K    |    A   |
|  2   | Billy   |  15K    |    A   |
|  3   | Bucky   |  15K    |    B   |

department table
| d_id | d_name  |
|----  |-------  |
|  A   |   XXX   | 
|  B   |   YYY   | 

Maintenant, d_id est une clé étrangère donc comment peut-elle être une clé primaire. Et expliquez quelque chose sur join . Quelle est son utilité ?

1 votes

Vous pouvez ajouter le SGBD que vous utilisez afin d'obtenir des exemples qui fonctionnent avec votre SGBD.

118voto

mvsagar Points 1089

Je pense que la question est un peu confuse.

Si vous voulez dire "une clé étrangère peut-elle "référencer" une clé primaire dans la même table ?", la réponse est un oui catégorique comme certains l'ont répondu. Par exemple, dans une table d'employés, une ligne pour un employé peut avoir une colonne pour stocker le numéro d'employé du manager où le manager est également un employé et donc aura une ligne dans la table comme une ligne de tout autre employé.

Si vous voulez dire "une colonne (ou un ensemble de colonnes) peut-elle être à la fois une clé primaire et une clé étrangère dans la même table ?", la réponse, à mon avis, est un non ; cela semble dénué de sens. Cependant, la définition suivante réussit dans SQL Server !

create table t1(c1 int not null primary key foreign key references t1(c1))

Mais je pense qu'il est inutile d'avoir une telle contrainte, à moins que quelqu'un ne propose un exemple pratique.

AmanS, dans votre exemple d_id ne peut en aucun cas être une clé primaire dans la table Employee. Une table ne peut avoir qu'une seule clé primaire. J'espère que cela clarifie votre doute. d_id est/peut être une clé primaire uniquement dans la table département.

0 votes

Il est clair pour moi que d_id est la clé primaire de la table département. d_id dans la table employé est également une clé étrangère. et vous mentionnez également que d_id peut être la clé primaire dans la même table (employé). mon professeur m'a dit que dans le cas d'une auto-jonction de la table employé cela peut être possible. ce point n'est pas clair pour moi, comment ?

1 votes

@AmanS, vous avez dit "vous mentionnez que d_id peut être une clé primaire dans la même table (employee)". Mais ce n'est pas le cas ; voici ma déclaration "AmanS, dans votre exemple d_id ne peut en aucun cas être une clé primaire dans la table Employee". J'espère que vous avez compris. Ce n'est pas possible, même dans le cas d'une jointure automatique. Une autre colonne d'une table peut faire référence à la clé primaire de la même table. Par exemple, créer une table employee(e_id int primary key, e_name varchar(30), e_mgr int, foreign key (e_mgr) references employee(e_id)). Il s'agit d'un cas de jointure automatique et e_mgr est une clé étrangère qui fait référence à la clé primaire e_id.

0 votes

Pouvez-vous me donner un exemple pratique de requête dans laquelle la clé étrangère peut se référer à la clé primaire ? mais la personne ci-dessous (ryvantage) a dit que cela ne peut pas être ..... Je suis confus, s'il vous plaît, aidez-moi.

28voto

Ceci peut être un bon exemple d'explication

CREATE TABLE employees (
id INTEGER NOT NULL PRIMARY KEY,
managerId INTEGER REFERENCES employees(id), 
name VARCHAR(30) NOT NULL
);

INSERT INTO employees(id, managerId, name) VALUES(1, NULL, 'John');
INSERT INTO employees(id, managerId, name) VALUES(2, 1, 'Mike');

-- Explication : -- Dans cet exemple. -- John est le manager de Mike. Mike ne gère personne. -- Mike est le seul employé qui ne gère personne.

17voto

ryvantage Points 2307

Bien sûr, pourquoi pas ? Disons que vous avez un Person table, avec id , name , age et parent_id , donde parent_id est une clé étrangère à la même table. Vous n'auriez pas besoin de normaliser le Person table pour Parent y Child des tables, ce serait exagéré.

~~

Person
| id |  name | age | parent_id |
|----|-------|-----|-----------|
|  1 |   Tom |  50 |      null |
|  2 | Billy |  15 |         1 |

Quelque chose comme ça.

~~

Je suppose que pour maintenir la cohérence, il faudrait qu'il y ait au moins 1 valeur nulle pour parent_id mais Le seul rang de "mâle alpha".

EDIT : Comme le montrent les commentaires, Sam a trouvé une bonne raison de ne pas le faire. Il semble que dans MySQL, lorsque vous tentez d'effectuer des modifications sur la clé primaire, même si vous spécifiez CASCADE ON UPDATE la modification ne sera pas propagée correctement. Bien que les clés primaires soient (généralement) interdites d'édition en production, il s'agit néanmoins d'une limitation à ne pas ignorer. Je modifie donc ma réponse en :- vous devriez probablement éviter cette pratique à moins que vous n'ayez un contrôle très strict du système de production (et que vous puissiez garantir que personne ne mettra en œuvre un contrôle qui modifie les PK). Je ne l'ai pas testé en dehors de MySQL.

0 votes

Voyez ma question modifiée avec un exemple. Votre réponse est-elle toujours oui ?

1 votes

Il ne fonctionne pas pour update . vérifier sqlfiddle.com/#!9/445052/1/0 et essayez ensuite d'ajouter Update menus set id = 6 WHERE id = 1; vous obtiendrez #1451 - Cannot delete or update a parent row

0 votes

@Sam deux choses : 1) Je comprends que cela ne fonctionne pas, mais je ne suis pas d'accord pour dire que cela devrait échouer. Avec une mise à jour en cascade, il ne semble pas y avoir de raison logique pour que la mise à jour échoue. 2) Qui change les PK dans des situations pratiques ? Les gens qui cherchent les ennuis lol

9voto

Nimya fa7 Points 109

Par exemple : n niveau de sous-catégorie pour les catégories. id est référencée par une clé étrangère sous_catégorie_id

enter image description here

2voto

bbe Points 210

Les listes imbriquées constituent un bon exemple d'utilisation des identifiants d'autres lignes de la même table comme clés étrangères.

La suppression d'une ligne qui a des enfants (c'est-à-dire des lignes qui font référence à l'identifiant du parent), qui ont également des enfants (c'est-à-dire qui font référence aux identifiants des enfants) supprimera une cascade de lignes.

Cela évitera bien des soucis (et beaucoup de code sur ce qu'il faut faire avec les orphelins - c'est-à-dire les lignes qui font référence à des identifiants inexistants).

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