web-dev-qa-db-fra.com

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 car la clé étrangère n'a pas la propriété uniqueness.

Mais certaines personnes ont dit que cela pouvait être le cas si elles rejoignaient la table. Je suis nouveau à 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 alors comment ça peut être une clé primaire. Et expliquer quelque chose à propos de join. Quel est son usage?

54
AmanS

Je pense que la question est un peu déroutant.

Si vous voulez dire "la clé étrangère peut-elle" se référer "à une clé primaire dans la même table?", La réponse est oui, certains 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 responsable où le responsable est également un employé et aura donc une ligne dans la table comme une ligne de n'importe quel autre employé.

Si vous voulez dire "une colonne (ou un ensemble de colonnes) peut-il être une clé primaire ainsi qu'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 que cela n'a pas de sens d'avoir une telle contrainte à moins que quelqu'un ne donne un exemple concret.

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 efface votre doute. d_id est/peut être une clé primaire uniquement dans la table department.

70
mvsagar

Bien sûr, pourquoi pas? Supposons que vous ayez une table Person avec id, name, age et parent_id, où parent_id est une clé étrangère à la même table. Vous n’auriez pas besoin de normaliser la table Person en Parent et Child, ce qui serait excessif.

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 au moins une valeur nulle pour parent_id, bien que. La rangée "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 essayez d’éditer la clé primaire, même si vous spécifiez CASCADE ON UPDATE il ne propage pas correctement le montage. Bien que les clés primaires soient (généralement) interdites à l'é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 sauf si vous avez un contrôle assez strict sur le système de production (et pouvez garantir que personne ne mettra en œuvre un contrôle qui modifie les PK). Je ne l'ai pas testé en dehors de MySQL.

16
ryvantage

Par exemple: n niveau de sous-catégorie pour les catégories. La clé primaire de la table inférieure , id est référencée par la clé étrangère sub_category_id

enter image description here

6
Nimya V

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.

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

La suppression d'une ligne comportant des enfants (c'est-à-dire des lignes qui font référence à l'identifiant du parent) et possédant également des enfants (c'est-à-dire référençant des identifiants d'enfants) supprimera une cascade de lignes.

Cela épargnera beaucoup de douleur (et beaucoup de code indiquant ce qu’il faut faire des orphelins - c’est-à-dire des lignes qui font référence à des identifiants non existants).

1
bbe