Depuis la version 3.23.43b, InnoDB respecte les contraintes de clé étrangères.
La syntaxe des définitions de contraintes de clés étrangères de InnoDB est la suivante :
[CONSTRAINT symbol] FOREIGN KEY [id] (index_col_name, ...) REFERENCES tbl_name (index_col_name, ...) [ON DELETE {CASCADE | SET NULL | NO ACTION | RESTRICT}] [ON UPDATE {CASCADE | SET NULL | NO ACTION | RESTRICT}]
Les deux tables doivent être de type InnoDB
,
dans la table, il doit y avoir un INDEX où les clés
étrangères sont listées comme première
colonne, dans le même ordre, et dans la table référencée, il
doit y avoir un INDEX où les colonnes référencées sont
listées comme premières colonnes, dans le
même ordre. Les préfixes d'index ne sont pas supportés pour
les clés de contrainte.
InnoDB
ne crée pas automatiquement les index
nécessaires pour les clés étrangères : vous devez ls créer
vous-même. Les index sont nécessaires pour accélérer les
vérifications de contrainte, et éviter un scan de table.
Les colonnes correspondantes de la contrainte dans la table et
la table de référence doivent avoir le même type, pour
éviter les conversions lors des comparaisons. La
taille et la présente du signe pour les
entiers doit être les mêmes. La taille des chaînes
doivent être les mêmes. Si vous spécifiez une action
SET NULL
, assurez vous que vous
n'avez pas déclaré les colonnes de la
table fille NOT NULL
.
Si MySQL vous retourne une numéro d'erreur 1005 lors de la
comande CREATE TABLE
, et un message d'erreur
de numéro 150, alors la création de la table a échoué à
cause de la contrainte de clé étrangère, qui n'a pas été
correctement formulée. Similairement, si une commande
ALTER TABLE
échoue et indique une erreur
150, c'est que la définition de la clé étrangère est
incorrectement formulée dans la table modifiée. Depuis la
version 4.0.13, vous pouvez utiliser la commande SHOW
INNODB STATUS
pour avoir une explication détaillée
de la dernière erreur de clé étrangère
InnoDB
sur le serveur.
Depuis la version 3.23.50, InnoDB
ne vérifie
pas la clé étrangère pour les clés étrangères ou les clés
référencées qui contienent des valeurs
NULL
.
Une entorse aux standards : si
dans la table parente, il y a plusieurs lignes qui ont la même
valeur de clé référencée, alors InnoDB
effectue les vérifications de clé étrangères comme si les
autres parents avec la même valeur de clé n'existaient pas.
Par exemple, si vous avez défini une contrainte de type
RESTRICT
et qu'il y a une ligne fille avec
plusieurs lignes parente, InnoDB
n'acceptera
pas l'effacement d'aucun des parents.
Depuis la version 3.23.50, vous pouvez aussi associer la clause
ON DELETE CASCADE
ou ON DELETE SET
NULL
avec la contrainte de clé étrangère. Les
options correspondante ON UPDATE
sont
disponibles depuis la version 4.0.8. Si ON DELETE
CASCADE
est spécifiée, et qu'une ligne de la table
parente est effacée, alors InnoDB
va
automatiquement effacer toute les lignes qui sont dans la table
fille et dont les valeurs de clé étrangère sont celles
référencées dans la ligne parente. Si ON DELETE SET
NULL
est spécifiée, les lignes filles sont
automatiquement modifiée pour que la colonne de la clé
étrangère prenne la valeur de NULL
.
Une entorse aux standards : si
ON UPDATE CASCADE
ou ON UPDATE SET
NULL
cascade récursivement jusqu'à la
même table, elle agira comme pour un
RESTRICT
. Cela est fait pour éviter les
boucles infinies des modifications en cascade. Une clause
ON DELETE SET NULL
auto-référente, d'un
autre coté, fonctionne depuis la version 4.0.13. La clause
ON DELETE CASCADE
auto-référente à
toujours fonctionné.
Un exemle :
CREATE TABLE parent(id INT NOT NULL, PRIMARY KEY (id) ) TYPE=INNODB; CREATE TABLE child(id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE ) TYPE=INNODB;
Voici un exemple plus complexe où la table
product_order
a des clés étrangères sur
deux tables. La première clé est un index à deux colonnes,
dans la table product
. Les autres clés sont
mono-colonnes, dans la table customer
:
CREATE TABLE product (category INT NOT NULL, id INT NOT NULL, price DECIMAL, PRIMARY KEY(category, id)) TYPE=INNODB; CREATE TABLE customer (id INT NOT NULL, PRIMARY KEY (id)) TYPE=INNODB; CREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT, product_category INT NOT NULL, product_id INT NOT NULL, customer_id INT NOT NULL, PRIMARY KEY(no), INDEX (product_category, product_id), FOREIGN KEY (product_category, product_id) REFERENCES product(category, id) ON UPDATE CASCADE ON DELETE RESTRICT, INDEX (customer_id), FOREIGN KEY (customer_id) REFERENCES customer(id)) TYPE=INNODB;
Depuis la version 3.23.50, InnoDB
vous permet
d'ajouter une nouvelle clé à une table, grâce à la syntaxe
ALTER TABLE yourtablename ADD [CONSTRAINT symbol] FOREIGN KEY [id] (index_col_name, ...) REFERENCES tbl_name (index_col_name, ...) [ON DELETE {CASCADE | SET NULL | NO ACTION | RESTRICT}] [ON UPDATE {CASCADE | SET NULL | NO ACTION | RESTRICT}]
N'oubliez pas de commencer par créer les
index nécessaires en premier!. Vous pouvez aussi
ajouter des clés étrangères reflexives, en utilisant la
commande ALTER TABLE
.
Depuis la version 4.0.13, InnoDB
supporte la
syntaxe ALTER TABLE
pour supprimer une clé
étrangère :
ALTER TABLE yourtablename DROP FOREIGN KEY fk_symbol
Si la clause FOREIGN KEY
inclut un nom de
contraite CONSTRAINT
lors de la création,
vous pouvez utiliser ce nom pour effacer la clé. Les
contraintes peuvent porter un nom depuis MySQL 4.0.18. SInon, la
valeur fk_symbol
est généré en interne par
InnoDB
lorsque la clé étrangère est
créée. Pour savoir quel symbole utiliser pour effacer une clé
étrangère, utilisez la commande SHOW CREATE
TABLE
. Par exemple :
mysql>SHOW CREATE TABLE ibtest11c\G
*************************** 1. row *************************** Table: ibtest11c Create Table: CREATE TABLE `ibtest11c` ( `A` int(11) NOT NULL auto_increment, `D` int(11) NOT NULL default '0', `B` varchar(200) NOT NULL default '', `C` varchar(175) default NULL, PRIMARY KEY (`A`,`D`,`B`), KEY `B` (`B`,`C`), KEY `C` (`C`), CONSTRAINT `0_38775` FOREIGN KEY (`A`, `D`) REFERENCES `ibtest11a` (`A`, `D`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `0_38776` FOREIGN KEY (`B`, `C`) REFERENCES `ibtest11a` (`B`, `C`) ON DELETE CASCADE ON UPDATE CASCADE ) TYPE=InnoDB CHARSET=latin1 1 row in set (0.01 sec) mysql>ALTER TABLE ibtest11c DROP FOREIGN KEY 0_38775;
Depuis MySQL version 3.23.50, l'analyseur
InnoDB
autorise l'utilisation des guillemets
obliques autour des noms de tables et colonnes dans une clause
FOREIGN KEY ... REFERENCES ...
. Depuis MySQL
4.0.5, l'analyseur InnoDB
prend aussi en
compte la variable système
lower_case_table_names
.
Dans InnoDB
en versions < 3.23.50,
ALTER TABLE
et CREATE
INDEX
ne doivent pas être utilisé avec des tables
qui ont des contraintes de clés étrangères, ou qui sont
référencées dans des clés étrangères : une commande
ALTER TABLE
supprime toutes les clés
étrangères qui sont définies pour cette table. Vous ne
devriez pas utiliser ALTER TABLE
sur la table
référencée, mais utiliser DROP TABLE
puis
CREATE TABLE
pour modifier le schéma.
Lorsque MySQL exécute la commande ALTER
TABLE
, il risque d'utiliser en interne la commande
RENAME TABLE
, et cela va poser des problèmes
pour les clés étrangères qui reposent sur cette table. Une
commande CREATE INDEX
est traitée par MySQL
comme une commande ALTER TABLE
, et ces
restrictions s'appliquent aussi.
Lorsqu'il vérifie les clés étrangères,
InnoDB
pose des verrous de lignes partagées
sur les lignes des tables qu'il utilise.
InnoDB
vérifie immédiatement les
contraintes de clés étrangères : la vérification n'attend
pas la validation de la transaction.
Si vous voulez ignorer les contraintes de clés étrangères
durant, par exemple, une opération de LOAD
DATA
, vous pouvez utiliser la commande SET
FOREIGN_KEY_CHECKS=0
.
InnoDB
vous permet d'effacer n'importe quelle
table, même si cela va casser les contraintes de clés
étranègres qui référence cette table. Lorsque vous supprimez
une table, la contrainte de clé étrangère qui y était
attachée est aussi supprimée.
Si vous recréez une table qui a été supprimée, sa définition doit se conformer aux contraintes des clés étrangères qui la référencent. Elle doit avoir les bons types et noms de colonnes, et doit avoir les bonnes clés, comme indiqué ci-dessus. Si ces contraintes ne sont pas vérifiées, MySQL vous gratifiera d'une erreur 1005, et vous enverra lire le message numéro 150.
Depuis la version 3.23.50 InnoDB
retourne la
définition de clé étrangère lorsque vous utilisez la
commande
SHOW CREATE TABLE tbl_name;
De plus, mysqldump
produit aussi les
définitions correctes de tables, sans oublier les clés
étrangères.
Vous pouvez aussi lister les clés étrangères d'une table
T
avec
SHOW TABLE STATUS FROM db_name LIKE 'tbl_name'
Les contraintes de clés étragnères sont listées dans les commentaires de la table.
Lors des vérifications des contraintes,
InnoDB
pose des verrous de lignes sur les
lignes parents ou enfants qu'il utilise.
InnoDB
vérifie immédiatement les
contraintes de clés : la vérification n'est pas reportée
jusqu'à la validation de la transaction.
Pour simplifier l'importation de données dans des tables qui
ont des contraintes, mysqldump
ajoute
automatiquement la commande qui met la variable
FOREIGN_KEY_CHECKS
à 0, depuis MySQL version
4.1.1. Cela évite des problèmes spécifiques avec les tables
qui doivent être chargées dans un ordre particulier. Pour les
versions antérieures, vous pouvez désactiver manuellement la
variable depuis mysql
lors du chargement du
fichier comme ceci :
mysql>SET FOREIGN_KEY_CHECKS = 0;
mysql>SOURCE dump_file_name;
mysql>SET FOREIGN_KEY_CHECKS = 1;
Cela vous permet de faire l'importation des données des tables
dans n'importe quel ordre. Cela accélère aussi l'opération
d'importation. FOREIGN_KEY_CHECKS
est
disponible depuis MySQL 3.23.52 et 4.0.3.
Mettre FOREIGN_KEY_CHECKS
à 0 peut aussi
être utile pour les opérations de LOAD
DATA
.
InnoDB
permet l'effacement de n'importe
quelle table, même si cela casse les contraintes de clés
étrangères. Lorsque vous effacez une table, les contraintes
définies sur cette table sont aussi effacées.
Si vous recréez une table qui a été effacée, elle doit avoir une définition qui est compatible avec les clés étrangères qui l'utilise. Elle doit avoir les bonnes colonnes et les index. Si cela n'est pas vrai, MySQL retourne une erreur 1005, et fait référence à un message d'erreur numéro 150.
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.