Désambiguïsation des colonnes/contraintes de clé étrangère
En supposant que vous faites référence aux contraintes de clé étrangère , la réponse courte serait vous ne les utilisez tout simplement pas .
Et voici la longue :
Nous avons l'habitude de désigner les colonnes comme des clés étrangères aux autres tableaux. Surtout pendant le processus de normalisation, des phrases comme "user_purchase.i_id
est une clé étrangère vers les items
tableau" serait très courant. Bien que ce soit une manière parfaitement valide de décrire la relation, elle peut devenir un peu floue lorsque nous atteignons la phase de mise en œuvre.
Supposons que vous ayez créé vos tables sans la FOREIGN KEY
clauses :
CREATE TABLE user(
id INT(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
password VARCHAR(20) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE items(
i_id INT(11) NOT NULL AUTO_INCREMENT,
name TINYTEXT NOT NULL,
price DECIMAL(8,2) NOT NULL,
PRIMARY KEY (i_id)
);
CREATE TABLE user_purchase(
i_id INT(11) NOT NULL,
name TINYTEXT NOT NULL,
id INT(11) NOT NULL,
);
Notez que, du point de vue relationnel, la clé étrangère colonnes sont toujours implémentés . Il y a une colonne qui référence le user
tableau (id
) et un autre qui référence les items
tableau (i_id
) -- mettons le name
colonne de côté un instant. Considérez les données suivantes :
user user_purchase items
| id username | | id i_id | | i_id name price |
| 23 john | | 55 10 | | 10 chocolate bar 3.42 |
| 55 mary | | 70 10 | | 33 mobile phone 82.11 |
| 70 fred | | 70 33 | | 54 toothpaste 8.67 |
| 55 10 | | 26 toy car 6.00 |
| 70 26 |
Le rapport est là. Il est implémenté au moyen du user_purchase
table, qui contient des informations sur qui a acheté quoi . Si nous devions interroger la base de données pour un rapport pertinent, nous ferions :
select * from user_purchase p
join user u on (p.id=u.id)
join items i on (p.i_id=i.i_id)
Et c'est ainsi que nous utilisons la relation et la clé étrangère colonnes impliqué.
Maintenant, et si nous faisions :
insert into user_purchase (id,i_id) values (23,99)
Apparemment, il s'agit d'une entrée invalide. Bien qu'il y ait un utilisateur avec id=23
, il n'y a pas d'élément avec i_id=99
. Le RDBMS permettrait que cela se produise, car il ne sait pas mieux . Encore.
C'est là que les contraintes de clé étrangère entrer en jeu. En spécifiant FOREIGN KEY (i_id) REFERENCES items(i_id)
dans le user_purchase
définition de table, nous donnons essentiellement au SGBDR une règle à suivre :entrées avec i_id
les valeurs qui ne sont pas contenues dans le items.i_id
colonne ne sont pas acceptables . En d'autres termes, alors qu'une colonne de clé étrangère implémente la référence , une contrainte de clé étrangère applique l'intégrité référentielle .
Notez, cependant, que le select
ci-dessus ne changerait pas, simplement parce que vous avez défini une contrainte FK. Ainsi, vous n'utilisez pas les contraintes FK, le SGBDR le fait, afin de protéger vos données.
Licenciements
Demandez-vous :pourquoi voudriez-vous cela ? Si les deux clés étrangères doivent servir le même objectif, la redondance finira par vous causer des ennuis. Considérez les données suivantes :
user_purchase items
| id i_id name | | i_id name price |
| 55 10 chocolate bar | | 10 chocolate bar 3.42 |
| 70 10 chocolate bar | | 33 mobile phone 82.11 |
| 70 33 mobile phone | | 54 toothpaste 8.67 |
| 55 10 toothpaste | | 26 toy car 6.00 |
| 70 26 toy car |
Quel est le problème avec cette image? L'utilisateur 55
acheter deux tablettes de chocolat, ou une tablette de chocolat et un dentifrice ? Ce type d'ambiguïté peut entraîner de nombreux efforts pour maintenir la synchronisation des données, ce qui serait inutile si nous ne gardions qu'une des clés étrangères. En fait, pourquoi ne pas laisser tomber le name
colonne entièrement, puisqu'elle est impliquée par la relation.
Bien sûr, nous pourrions résoudre ce problème en implémentant une clé étrangère composite, en définissant PRIMARY KEY(i_id,name)
pour les items
table (ou en définissant un UNIQUE(i_id,name)
supplémentaire index, cela n'a pas vraiment d'importance) puis en définissant un FOREIGN KEY(i_id,name) REFERENCES items(i_id,name)
. De cette façon, seuls les couples (i_id,name) qui existent dans les items
table serait valide pour user_purchases
. Outre le fait que vous en auriez encore un clé étrangère , cette approche est totalement inutile, à condition que le i_id
la colonne est déjà suffisante pour identifier un élément (on ne peut pas en dire autant pour le name
colonne...).
Cependant, il n'y a pas de règle interdisant l'utilisation de plusieurs clés étrangères pour une table. En fait, il y a des circonstances qui exigent une telle approche. Prenons une person(id,name)
table et un parent(person,father,mother)
un, avec les données suivantes :
person parent
| id name | | person father mother |
| 14 John | | 21 14 59 |
| 43 Jane | | 14 76 43 |
| 21 Mike |
| 76 Frank |
| 59 Mary |
Évidemment, les trois colonnes du parent
table sont des clés étrangères pour person
. Pas pour la même relation , cependant, mais pour trois différents :Comme les parents d'une personne sont aussi des personnes, les deux colonnes correspondantes doivent référencer la même table person
Est-ce que. Notez cependant que non seulement les trois champs peuvent mais aussi doivent parrainer une person
différente s dans le même parent
ligne, puisque personne n'est son propre parent et que le père de personne n'est pas non plus sa mère.