Les clés étrangères font partie intégrante de la création d'une relation dans les bases de données relationnelles. Voici pourquoi et comment les créer.
Nous avons donc établi qu'une clé primaire fournit un identifiant unique pour la table. Mais les clés primaires ne sont pas le seul type de "clé". Notre base de données peut également contenir des clés étrangères.
Qu'est-ce qu'une clé étrangère ?
Une clé étrangère est une colonne (ou un ensemble de colonnes) dans une table qui identifie de manière unique une ligne d'une autre table. Ceci définit une relation entre les deux tables.
Une clé étrangère vous permet de croiser les données associées entre les tables. Cela s'avère pratique lorsqu'une colonne contient des données représentées dans une autre table.
Exemple
Voici un schéma de notre FruitShop base de données montrant la relation entre le Fruit table et les Unités table.
La ligne noire qui relie les deux tables indique une clé étrangère. L' UnitId champ sur le Fruit table est une clé étrangère vers UnitId champ sur les Unités table. Par conséquent, la valeur que nous insérons dans Fruit.UnitId doit correspondre à une valeur dans Units.UnitId . Cela active le Fruit.UnitId pour référencer les données dans les autres colonnes de cet enregistrement (c'est-à-dire l'enregistrement qui a l' UnitId correspondant ).
Les données
Donc, si notre Fruit table contient un enregistrement comme celui-ci :
FruitId | NomFruit | Inventaire | ID d'unité | Date d'entrée | Date de mise à jour |
---|---|---|---|---|---|
1 | Pomme | 10 | 3 | 2012-11-27 12:42:10 | 2012-11-27 12:42:10 |
Et nos Unités table contient les enregistrements suivants :
ID d'unité | NomUnité | Date d'entrée | Date de mise à jour |
---|---|---|---|
1 | Pièce | 2011-12-30 12:46:15 | 2011-12-30 12:46:15 |
2 | Groupe | 2011-12-30 12:46:15 | 2011-12-30 12:46:15 |
3 | Kilogramme | 2011-12-30 12:46:15 | 2011-12-30 12:46:15 |
4 | Conteneur | 2011-12-30 12:46:15 | 2011-12-30 12:46:15 |
5 | Livre | 2011-12-30 12:46:15 | 2011-12-30 12:46:15 |
6 | Once | 2011-12-30 12:46:15 | 2011-12-30 12:46:15 |
Vous pouvez voir que le
Fruit.UnitId
le champ contient un 3
. Regardez maintenant les
Unités
table pour l'enregistrement qui contient un 3
dans
UnitId
domaine. Vous pouvez voir que cet enregistrement représente
Kilogramme
. Par conséquent, nous savons maintenant que les pommes sont mesurées en kilogrammes.
La bonne chose à propos de la configuration de la base de données de cette manière est que nous n'avons pas besoin de répéter "Kilogrammes" pour chaque enregistrement qui utilise cette unité. La réduction de la duplication est un avantage clé des systèmes de gestion de bases de données relationnelles.
Voir autant d'enregistrements dans le Fruit table partagera le même nom d'unité (par exemple, "Kilograms", "Container", "Bunch", etc.), nous devons réfléchir attentivement avant d'ajouter des doublons à notre base de données. Sans utiliser de relation de clé étrangère, nous pourrions simplement écrire les noms d'unités directement dans le Fruit table (et appelez peut-être la colonne "Unit", "UnitType" ou "UnitName"). Ensuite, nous nous retrouverions avec de nombreux enregistrements partageant la même valeur pour la colonne du nom de l'unité. Nous verrions "Kilogram" répété encore et encore contre de nombreux disques. Nous verrions également "Bunch" répété, et tout autre type d'unité populaire.
Bien qu'il ne soit pas nécessairement "erroné" de le faire, il est généralement plus efficace de stocker un enregistrement pour chacun de ces noms d'unité dans une table séparée, puis de référencer cette table via le UnitId colonne. Cela est plus efficace que de répéter ces noms d'unité encore et encore pour chaque enregistrement créé dans Fruits table. Cela facilite également la tâche si jamais nous décidons de mettre à jour un nom d'unité (changer "Kilogrammes" en "Kilos" par exemple). Si nous mettons à jour un nom d'unité, cela n'affectera pas le Fruit table car UnitId restera le même. De plus, cela permet également d'éviter que des données incohérentes n'apparaissent dans notre base de données.
Contrainte de clé étrangère
Une contrainte de clé étrangère est un objet de base de données qui aide à maintenir la cohérence de vos données de clé étrangère. Vous créez une contrainte de clé étrangère pour maintenir l'intégrité référentielle. En créant une contrainte de clé étrangère, vous dites à MySQL d'appliquer certaines règles sur les données. Lorsque des données sont insérées, supprimées ou mises à jour, MySQL vérifie qu'elles respectent la clé étrangère que vous avez créée entre les tables. Si ce n'est pas le cas, cela empêchera les données d'être écrites/écrasées/supprimées, maintenant ainsi l'intégrité référentielle.
Par exemple, si un utilisateur essaie d'entrer une valeur UnitId dans Fruit.UnitId mais il n'y a pas d'enregistrement correspondant dans Units.UnitId colonne, MySQL empêchera l'utilisateur d'entrer cette valeur.
Lorsque nous avons créé nos deux tables, nous avons ajouté une contrainte de clé étrangère au Fruit table. Voici le code que nous avons utilisé pour créer la contrainte :
CONSTRAINT fkFruitUnits FOREIGN KEY (UnitId) REFERENCES Units (UnitId) ON DELETE RESTRICT ON UPDATE CASCADE
Lorsque vous développez les nœuds dans le SCHEMAS de gauche , vous pouvez voir la clé étrangère que nous avons créée (ainsi que les clés primaires) :
Si vous essayez d'insérer des données non conformes à la contrainte de clé étrangère, vous devriez obtenir une erreur.
Par exemple, si j'essaie d'insérer un enregistrement dans le champ Fruit table en utilisant un UnitId valeur qui n'existe pas dans les Unités table, je reçois l'erreur suivante :
Cela se produit parce que j'essaie d'insérer une valeur de 5
dans
UnitId
lorsqu'il n'y a pas de valeur correspondante dans
Units.UnitId
champ.
Pour que cela réussisse, je devrais m'assurer qu'il y a un enregistrement dans les
Unités
table avec un
UnitId
de 5
.
La clé étrangère ne fonctionne pas ?
Vous pouvez rencontrer la situation occasionnelle où une clé étrangère ne semble pas fonctionner. Par exemple, vous pouvez réussir à insérer des données dans une table même s'il existe une clé étrangère qui devrait empêcher l'insertion de ces données.
Il y a plusieurs choses que vous pouvez vérifier dans cette situation.
- Assurez-vous d'avoir ajouté
ON DELETE
etON UPDATE
clauses dans votre code. Par exemple,ON DELETE RESTRICT ON UPDATE CASCADE
. Consultez notre exemple CREATE TABLE pour savoir quand placer ce code. - Assurez-vous que la table est InnoDB . Vous pouvez le faire en ajoutant
ENGINE=InnoDB
à la fin de votreCREATE TABLE
déclaration (voir mon exemple lorsque nous avons créé nos tables). Certains moteurs (tels que MyISAM ) ne prennent pas en charge les contraintes de clé étrangère, mais ils ne fournissent aucun avertissement à ce sujet lorsque vous tentez de créer votre contrainte de clé étrangère. Si votre moteur par défaut n'est pas InnoDB alors il est probable que vos clés étrangères ne seront pas prises en charge. - Assurez-vous que MySQL vérifie réellement les clés étrangères. Vous pouvez le faire en exécutant le code suivant :
SET FOREIGN_KEY_CHECKS=1
.
Désactiver la vérification des clés étrangères
Il peut arriver que les contraintes de clé étrangère deviennent inutilement restrictives, au point d'entraver considérablement vos efforts de chargement des données. Par exemple, lorsque vous venez de créer une base de données et que vous devez charger les données initiales. Ou si vous avez besoin de supprimer un tas de tables et de recharger les données.
Si vous ne chargez pas les données dans le bon ordre, vous continuerez probablement à recevoir des erreurs de clé étrangère en raison du chargement des données dans le mauvais ordre (c'est-à-dire que vous essayez de charger les tables enfants avant que les tables parents aient eu leur données chargées).
Ce n'est pas seulement un problème de chargement les données. Vous pouvez également rencontrer ce problème lors de la création de la base de données en premier lieu. Si vous ne créez pas les tables dans le bon ordre, vous risquez de rencontrer des erreurs dues à des contraintes de clé étrangère.
Si vous ne connaissez pas l'ordre parent-enfant correct, l'établissement de l'ordre correct pour créer la base de données ou charger les données peut prendre beaucoup de temps et d'efforts. Dans de tels cas, vous feriez peut-être mieux de dire temporairement à MySQL de ne pas vérifier les clés étrangères pour le moment.
Vous pouvez désactiver la vérification des clés étrangères avec le code suivant :
FOREIGN_KEY_CHECKS=0
Pour l'activer à nouveau, procédez comme suit :
FOREIGN_KEY_CHECKS=1