web-dev-qa-db-fra.com

Erreur MySQL 1215: Impossible d'établir une contrainte de clé étrangère

J'essaie de transférer l'ingénierie de mon nouveau schéma sur mon serveur de base de données, mais je ne comprends pas pourquoi j'obtiens cette erreur. J'ai essayé de chercher la réponse ici, mais tout ce que j'ai trouvé a dit de définir le moteur de base de données sur Innodb ou de vérifier que les clés que j'essaie d'utiliser comme clé étrangère sont des clés primaires dans leurs propres tables . J'ai fait ces deux choses, si je ne me trompe pas. Toute autre aide que vous pourriez offrir?

Executing SQL script in server

ERROR: Error 1215: Cannot add foreign key constraint

-- -----------------------------------------------------
-- Table `Alternative_Pathways`.`Clients_has_Staff`
-- -----------------------------------------------------

CREATE  TABLE IF NOT EXISTS `Alternative_Pathways`.`Clients_has_Staff` (
  `Clients_Case_Number` INT NOT NULL ,
  `Staff_Emp_ID` INT NOT NULL ,
  PRIMARY KEY (`Clients_Case_Number`, `Staff_Emp_ID`) ,
  INDEX `fk_Clients_has_Staff_Staff1_idx` (`Staff_Emp_ID` ASC) ,
  INDEX `fk_Clients_has_Staff_Clients_idx` (`Clients_Case_Number` ASC) ,
  CONSTRAINT `fk_Clients_has_Staff_Clients`
    FOREIGN KEY (`Clients_Case_Number` )
    REFERENCES `Alternative_Pathways`.`Clients` (`Case_Number` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_Clients_has_Staff_Staff1`
    FOREIGN KEY (`Staff_Emp_ID` )
    REFERENCES `Alternative_Pathways`.`Staff` (`Emp_ID` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB

Exécution du script SQL terminée: instructions: 7 réussies, 1 échouée

Voici le code SQL pour les tables parent.

CREATE  TABLE IF NOT EXISTS `Alternative_Pathways`.`Clients` (
  `Case_Number` INT NOT NULL ,
  `First_Name` CHAR(10) NULL ,
  `Middle_Name` CHAR(10) NULL ,
  `Last_Name` CHAR(10) NULL ,
  `Address` CHAR(50) NULL ,
  `Phone_Number` INT(10) NULL ,
  PRIMARY KEY (`Case_Number`) )
ENGINE = InnoDB

CREATE  TABLE IF NOT EXISTS `Alternative_Pathways`.`Staff` (
  `Emp_ID` INT NOT NULL ,
  `First_Name` CHAR(10) NULL ,
  `Middle_Name` CHAR(10) NULL ,
  `Last_Name` CHAR(10) NULL ,
  PRIMARY KEY (`Emp_ID`) )
ENGINE = InnoDB
275
Robert B

Je suppose que Clients.Case_Number et/ou Staff.Emp_ID ne sont pas exactement le même type de données que Clients_has_Staff.Clients_Case_Number et Clients_has_Staff.Staff_Emp_ID.

Peut-être que les colonnes dans les tables parent sont INT UNSIGNED?

Ils doivent correspondre exactement au même type de données dans les deux tables.

496
Ike Walker

Raisons pour lesquelles vous pouvez obtenir une erreur de contrainte de clé étrangère:

  1. Vous n'utilisez pas InnoDB comme moteur sur toutes les tables.
  2. Vous essayez de référencer une clé inexistante sur la table cible. Assurez-vous qu'il y a une clé sur l'autre table (il peut s'agir d'une clé primaire ou unique)
  3. Les types de colonnes ne sont pas les mêmes (exception: la colonne de la table de référence peut être nullable).
  4. Si le PK/FK est un varchar, assurez-vous que le classement est le même pour les deux.

Mettre à jour:

  1. L'une des raisons peut également être que la colonne que vous utilisez pour ON DELETE SET NULL n'est pas définie comme étant null. Assurez-vous donc que la colonne est définie sur null par défaut.

Vérifiez ces.

199
Explosion Pills

Pour d'autres, la même erreur peut ne pas toujours être due à une incompatibilité de type de colonne, vous pouvez en savoir plus sur une erreur de clé mysql foriegn en émettant une commande

SHOW ENGINE INNODB STATUS;

vous pouvez trouver une erreur près du haut du message imprimé quelque chose comme

Impossible de trouver un index dans la table référencée où le les colonnes référencées apparaissent en tant que premières colonnes ou types de colonnes dans la table et la table référencée ne correspondent pas pour la contrainte.

74
arvind

L'erreur 1215 est ennuyeuse. La réponse de la pilule d'explosion couvre les bases. Vous voulez vous assurer de commencer à partir de là. Cependant, il y a plus, beaucoup plus de cas subtils à surveiller:

Par exemple, lorsque vous essayez de relier des clés PRIMARY KEY de différentes tables, veillez à fournir les options ON UPDATE et ON DELETE appropriées. Par exemple.:

...
PRIMARY KEY (`id`),
FOREIGN KEY (`id`) REFERENCES `t` (`other_id`) ON DELETE SET NULL
....

ne volera pas, car les clés primaires (telles que id) ne peuvent pas être NULL.

Je suis convaincu que l'ajout de ce type de contraintes pose des problèmes encore plus subtils et similaires. C'est pourquoi, lorsque vous rencontrez des erreurs de contrainte, veillez toujours à ce que les contraintes et leurs implications aient un sens dans votre contexte actuel. Bonne chance avec votre erreur 1215!

12
Domi

Vérifiez le classement des tables à l’aide de SHOW TABLE STATUS , vous pouvez vérifier les informations relatives aux tables, y compris le classement.

Les deux tables doivent avoir le même classement.

Il m'est arrivé 

7
Carlos Laspina

Dans mon cas, j'avais supprimé une table en utilisant SET FOREIGN_KEY_CHECKS=0, puis SET FOREIGN_KEY_CHECKS=1 après. Quand je suis allé recharger la table, j'ai eu error 1215. Le problème était qu'il y avait une autre table dans la base de données qui avait une clé étrangère à la table que j'avais supprimée et rechargée. Une partie du processus de rechargement impliquait la modification d'un type de données pour l'un des champs, ce qui rendait la clé étrangère de l'autre table invalide, déclenchant ainsi error 1215. J'ai résolu le problème en supprimant puis en rechargeant l'autre table avec le nouveau type de données pour le champ concerné.

7
CodeMed

Il y a un écueil que j'ai rencontré avec "Erreur 1215: impossible d'ajouter une contrainte de clé étrangère" lors de l'utilisation de Laravel 4, en particulier avec les générateurs Laravel 4 de JeffreyWay.

Dans Laravel 4, vous pouvez utiliser les générateurs de JeffreyWay pour générer des fichiers de migration afin de créer des tableaux un par un, ce qui signifie que chaque fichier de migration génère un tableau . Vous devez être conscient du fait que chaque fichier de migration est généré avec un horodatage dans le nom du fichier, qui donne un ordre aux fichiers. L'ordre de génération est également l'ordre d'opération de migration lorsque vous lancez la commande Artisan CLI "php artisan migrate" . Ainsi, si un fichier demande une contrainte de clé étrangère faisant référence à une clé qui sera, mais pas encore, généré dans un dernier fichier, l'erreur 1215 est déclenchée . Dans ce cas, vous devez ajuster l'ordre de génération des fichiers de migration. Générez les nouveaux fichiers dans le bon ordre, copiez le contenu, puis supprimez les anciens fichiers désordonnés.

5
user2975399

J'ai eu la même erreur en essayant d'ajouter un fk. Dans mon cas, le problème était dû à la PK de la table FK qui était marquée comme non signée.

4
Alex

Une autre raison: si vous utilisez ON DELETE SET NULLtoutes les colonnes utilisées dans la clé étrangère, vous devez autoriser les valeurs NULL. Quelqu'un d'autre l'a découvert dans cette question

D'après ce que j'ai compris, l'intégrité des données ne poserait pas de problème, mais il semble que MySQL ne supporte tout simplement pas cette fonctionnalité (en 5.7).

2
robsch

Vérifiez la compatibilité des tables. Par exemple, si l'une des tables est MyISAM et l'autre InnoDB, vous pouvez avoir ce problème.

2
Dennis

Pour MySQL (INNODB) ..., obtenez les définitions des colonnes que vous souhaitez lier.

SELECT * FROM information_schema.columns WHERE 
TABLE_NAME IN (tb_name','referenced_table_name') AND 
COLUMN_NAME  IN ('col_name','referenced_col_name')\G

comparer et vérifier les deux définitions de colonne ont 

même COLUMN_TYPE (longueur), même COLATION 

pourrait être utile de jouer comme

set foreign_key_checks=0;
ALTER TABLE tb_name ADD FOREIGN KEY(col_name) REFERENCES ref_table(ref_column) ON DELETE ...
set foreign_key_checks=1;
2
bortunac

Je ne trouve pas cette erreur

CREATE TABLE RATING (

Riv_Id INT(5),
Mov_Id INT(10) DEFAULT 0,
Stars INT(5),
Rating_date DATE, 

PRIMARY KEY (Riv_Id, Mov_Id),

FOREIGN KEY (Riv_Id) REFERENCES REVIEWER(Reviewer_ID)
ON DELETE SET NULL ON UPDATE CASCADE,

FOREIGN KEY (Mov_Id) REFERENCES MOVIE(Movie_ID)
ON DELETE SET DEFAULT ON UPDATE CASCADE
)
2
gathila

Cela se produit également lorsque le type des colonnes n'est pas le même.

par exemple. Si la colonne à laquelle vous faites référence est UNSIGNED INT et que la colonne à laquelle vous faites référence est INT, vous obtenez cette erreur.

2
Mozaffar

j'ai eu le même problème, ma solution:

Avant:

CREATE TABLE EMPRES
( NoFilm smallint NOT NULL

  PRIMARY KEY (NoFilm)

  FOREIGN KEY (NoFilm) REFERENCES cassettes

);

Solution:

CREATE TABLE EMPRES
(NoFilm smallint NOT NULL REFERENCES cassettes,

 PRIMARY KEY (NoFilm)

);

J'espère que c'est de l'aide;)

2
Yacine Richthofen

J'ai vécu cette erreur pour une raison complètement différente. J'ai utilisé MySQL Workbench 6.3 pour créer mon modèle de données (outil génial). J'ai remarqué que lorsque l'ordre des colonnes défini dans la définition de contrainte de clé étrangère ne correspond pas à la séquence des colonnes du tableau, cette erreur est également générée.

Cela m'a pris environ 4 heures pour essayer tout le reste mais vérifier cela.

Maintenant tout fonctionne bien et je peux revenir au codage. :-)

1
Stephen Nortje

Wooo je viens de l'obtenir! C'était un mélange de beaucoup de réponses déjà postées (innoDB, non signé, etc.). Cependant, une chose que je n’ai pas vue ici est la suivante: si votre FK pointe sur une PK, assurez-vous que la colonne source a une valeur qui a du sens. Par exemple, si la PC est un mediumint (8), assurez-vous que la colonne source contient également un mediumint (8). Cela faisait partie du problème pour moi.

1
Chris Neve

Pour moi, c'était les types de colonne. BigINT! = INT. 

Mais alors cela n'a toujours pas fonctionné. 

Alors j'ai vérifié les moteurs. Assurez-vous que Table1 = InnoDB et Table = InnoDB

1
Chad

Lorsque cette erreur se produit car la table référencée utilise le moteur MyISAM, cette réponse permet de convertir rapidement votre base de données. Toutes les tables de modèles Django utilisent donc InnoDB: https://stackoverflow.com/a/15389961/2950621

C'est une commande de gestion Django appelée convert_to_innodb.

1
nmgeek

Je voulais juste ajouter ce cas aussi pour la relation VARCHAR clé étrangère. J'ai passé la semaine dernière à essayer de comprendre cela dans MySQL Workbench 8.0 et j'ai finalement réussi à corriger l'erreur.

Réponse courte: Le jeu de caractères et le classement du schéma, de la table, de la colonne, de la table de référence, de la colonne de référence et de toute autre table faisant référence à la table parente doivent correspondre. 

Réponse longue: J'avais un type de données ENUM dans mon tableau. J'ai changé ceci en VARCHAR et je peux obtenir les valeurs d'une table de référence afin de ne pas avoir à modifier la table parent pour ajouter des options supplémentaires. Cette relation clé étrangère semblait simple, mais j'ai une erreur 1215. La réponse de arvind et la suivante link suggèrent l’utilisation de 

SHOW ENGINE INNODB STATUS;

En utilisant cette commande, j'ai reçu la description détaillée de l'erreur, sans information utile supplémentaire.

Impossible de trouver un index dans la table référencée où le les colonnes référencées apparaissent en tant que premières colonnes ou types de colonnes dans la table et la table référencée ne correspondent pas pour la contrainte. Notez que le type de stockage interne ENUM et SET a changé dans les tables créées avec> = InnoDB-4.1.12, et les colonnes de ce type dans les anciennes tables ne peuvent pas être référencés par de telles colonnes dans les nouvelles tables. Veuillez vous référer à http://dev.mysql.com/doc/refman/8.0/en/innodb-foreign-key-constraints.html pour obtenir la définition correcte de la clé étrangère.

Après quoi, j’ai utilisé SET FOREIGN_KEY_CHECKS=0; comme suggéré par Arvind Bharadwaj et le lien ici :

Cela a donné le message d'erreur suivant:

Code d'erreur: 1822. Impossible d'ajouter la contrainte de clé étrangère. Manquant index pour contrainte

À ce stade, j'ai «ingénierie inverse» le schéma et j'ai pu créer la relation de clé étrangère dans le diagramme EER. En 'forward engineering'-ing, j'ai eu l'erreur suivante:

Erreur 1452: Impossible d'ajouter ou de mettre à jour une ligne enfant: contrainte de clé étrangère échoue

Lorsque j'ai transféré le diagramme EER à un nouveau schéma, le script SQL s'est exécuté sans problème. En comparant le code SQL généré à partir des tentatives de transfert d'ingénieur, j'ai constaté que la différence résidait dans le jeu de caractères et le classement. La table parent, la table enfant et les deux colonnes contenaient le jeu de caractères utf8mb4 et le classement utf8mb4_0900_ai_ci; toutefois, une autre colonne de la table parent a été référencée à l'aide de CHARACTER SET = utf8 , COLLATE = utf8_bin ; dans une autre table enfant.

Pour l'ensemble du schéma, j'ai modifié le jeu de caractères et le classement de toutes les tables et de toutes les colonnes comme suit:

CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci;

Cela a finalement résolu mon problème avec l'erreur 1215.

Côté Remarque: Le classement utf8mb4_general_ci fonctionne dans MySQL Workbench version 5.0 ou ultérieure. La collation utf8mb4_0900_ai_ci ne fonctionne que pour MySQL Workbench 8.0 ou supérieur. Je pense qu'une des raisons pour lesquelles j'ai eu des problèmes avec le jeu de caractères et le classement est due à la mise à niveau de MySQL Workbench vers la version 8.0 entre les deux. Voici un link qui en dit plus sur cette collation.

1
CoderBapu

Dans mon cas, j'ai dû désactiver les contrôles FOREIGN KEY car les tables sources n'existaient pas.

SET FOREIGN_KEY_CHECKS=0;

0
Arvind Bhardwaj

Ceci est une version subtile de ce qui a déjà été dit, mais dans mon cas, j'avais 2 bases de données (foo et bar). J'ai d'abord créé foo et je n'ai pas réalisé qu'il faisait référence à une clé étrangère dans bar.baz (qui n'a pas encore été créée). Lorsque j'ai essayé de créer bar.baz (sans clé étrangère), j'ai continué à avoir cette erreur. Après avoir regardé pendant un moment, j'ai trouvé la clé étrangère dans foo.

Donc, si vous obtenez cette erreur, vous pouvez avoir une clé étrangère préexistante à la table en cours de création.

0
ajon

Soyez conscient de l'utilisation des citations arrière aussi. J'ai eu dans un script la déclaration suivante

ALTER TABLE service ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`;

mais les citations à la fin étaient fausses. Cela aurait dû être:

ALTER TABLE service ADD FOREIGN KEY (create_by) REFERENCES `system_user`(`id`);

MySQL ne donne malheureusement pas de détails sur cette erreur ...

0
Olivier Faucheux

Je sais que je suis très tard pour la fête mais je veux le mettre ici pour qu'il soit listé.

En plus de tous les conseils ci-dessus pour vous assurer que les champs sont définis de manière identique et que les types de table ont le même classement, veillez à ne pas commettre l'erreur de recrue en essayant de lier des champs lorsque les données du champ CHILD ne sont pas déjà dans le champ PARENT. Si vous avez des données dans le champ ENFANT que vous n'avez pas encore entrées dans le champ PARENT, cela provoquera cette erreur. C'est dommage que le message d'erreur ne soit pas un peu plus utile.

En cas de doute, sauvegardez la table contenant la clé étrangère, supprimez toutes les données, puis essayez de créer la clé étrangère. En cas de succès, alors que faire?

Bonne chance.

0
noowie

Pour moi, l'erreur 1215 s'est produite lors de l'importation d'un fichier de vidage créé par mysqldump, qui crée les tables par ordre alphabétique, ce qui a amené dans mon cas des clés étrangères à faire référence à des tables créées ultérieurement dans le fichier. (Accessoires à cette page pour le signaler: https://www.percona.com/blog/2017/04/06/dealing-mysql-error-code-1215-cannot-add-foreign-key-constraint/ )

Puisque mysqldump ordonne les tables par ordre alphabétique et que je ne veux pas changer les noms des tables, j'ai suivi les instructions de la réponse de JeremyWeir sur cette page , qui indique de mettre set FOREIGN_KEY_CHECKS = 0; en haut du fichier de vidage et de mettre SET FOREIGN_KEY_CHECKS = 1; à le bas du fichier de vidage.

Cette solution a fonctionné pour moi.

0
Arya

Une autre source de cette erreur est que vous avez 2 ou plusieurs noms de table identiques qui portent les mêmes noms de clés étrangères. Cela arrive parfois aux personnes qui utilisent des logiciels de modélisation et de conception, tels que Mysql Workbench, et qui génèrent ultérieurement le script à partir de la conception. 

0
Dima Dz

Ajouter une autre raison à @ Les pilules d'explosion répondent ci-dessus :

7- Lors de l'utilisation de clés multi-colonnes, l'ordre dans la création de la clé étrangère doit correspondre à l'autre dans l'ordre des colonnes du tableau.

0
RADU