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

174

Tableau 1

+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| UserID   | int(11)     | NO   | PRI | NULL    | auto_increment |
| Password | varchar(20) | NO   |     |         |                |
| Username | varchar(25) | NO   |     |         |                |
| Email    | varchar(60) | NO   |     |         |                |
+----------+-------------+------+-----+---------+----------------+

Tableau 2

+------------------+--------------+------+-----+---------+----------------+
| Field            | Type         | Null | Key | Default | Extra          |
+------------------+--------------+------+-----+---------+----------------+
| UserID           | int(11)      | NO   | MUL |         |                |
| PostID           | int(11)      | NO   | PRI | NULL    | auto_increment |
| Title            | varchar(50)  | NO   |     |         |                |
| Summary          | varchar(500) | NO   |     |         |                |
+------------------+--------------+------+-----+---------+----------------+

Erreur:

com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: 
Cannot add or update a child row: a foreign key constraint fails 
(`myapp/table2`, CONSTRAINT `table2_ibfk_1` FOREIGN KEY (`UserID`) 
REFERENCES `table1` (`UserID`)) 

Qu'est ce que j'ai mal fait? J'ai lu http://www.w3schools.com/Sql/sql_foreignkey.asp et je ne vois pas ce qui ne va pas.

À M
la source
4
Pouvez-vous publier la requête qui a déclenché l'erreur?
Humide le
38
En un mot, vous essayez d'insérer / mettre à jour une valeur dans table2.UserIDqui n'existe pas dans table1.UserID.
Joe Stefanelli
Je ne sais pas pourquoi mais après avoir déplacé ma base de données d'un environnement Windows vers Linux, j'ai dû supprimer et recréer une relation (c'est là que j'ai remarqué le problème). La valeur existait, mais la suppression et la réajout de la relation l'ont corrigée. Vous devrez peut-être faire très attention en le faisant évidemment.
johnsnails

Réponses:

235

Vous obtenez cette erreur car vous essayez d'ajouter / de mettre à jour une ligne table2qui n'a pas de valeur valide pour le UserIDchamp en fonction des valeurs actuellement stockées dans table1. Si vous publiez plus de code, je peux vous aider à diagnostiquer la cause spécifique.

Brian Driscoll
la source
PreparedStatement st = connection.prepareStatement ("Insérer dans table2 (UserID, PostID, Title, Summary)" + "valeurs (UserID,?,?,?)");
Tom
15
je ne sais pas à quoi sert le vote négatif; ma réponse est parfaitement valable et correcte.
Brian Driscoll
Hmm ... ce n'est certainement pas une bonne idée de mélanger des paramètres nommés avec des paramètres sans nom dans votre instruction préparée. il doit s'agir de "valeurs (?,?,?,?)" avec la valeur appropriée pour l'ID utilisateur spécifié dans votre instruction d'exécution.
Brian Driscoll
J'ai donc besoin de faire une autre instruction SQL pour obtenir l'ID utilisateur de table1?
Tom
5
Très probablement un 0, remplacez-le par Null si c'est le cas
Jeffrey Nicholson Carré
123

Cela signifie que vous essayez d'insérer dans table2une UserIDvaleur qui n'existe pas dans table1.

Rami C
la source
104

Un simple piratage peut être de désactiver les vérifications de clé étrangère avant d'effectuer toute opération sur la table. Requête simplement

SET FOREIGN_KEY_CHECKS=0

Cela désactivera la correspondance de clé étrangère avec toutes les autres tables. Une fois que vous avez terminé avec le tableau, réactivez-le

SET FOREIGN_KEY_CHECKS=1

Cela fonctionne pour moi plusieurs fois.

Sandeep Giri
la source
Comment j'utilise ceci ??
Sachin de Pune
2
@SachinfromPune ajoutez simplement SET FOREIGN_KEY_CHECKS = 0; au démarrage du fichier mysql et SET FOREIGN_KEY_CHECKS = 1; à la fin du fichier mysql, réimporter les données
inrsaurabh
1
N'est-ce pas problématique? Vous perdez l'intégrité référentielle, non?
roadrunner66
L'intégrité référentielle est prise en charge par la présence des entrées d'index correctes. Tant que vous avez correctement vos clés et vos index, vous devriez pouvoir désactiver la vérification des clés lors d'une saisie groupée.
Vernon Keenan le
46

J'ai découvert un autre cas étrange: si vous créez accidentellement une clé étrangère d'une table InnoDB vers une table MyISAM, MySQL génère cette erreur au moment de l'insertion même si les données sont valides par ailleurs.

Voir http://nick.zoic.org/art/mysql-foreign-key-error/

NickZoic
la source
1
Oui, j'ai le même problème. Deux tables devraient être InnoDB!
emeraldhieu
2
J'ai eu le même problème, merci pour le tuyau. Voici un lien vers la documentation MySQL sur la façon de convertir des tables de MyISAM en InnoDB dev.mysql.com/doc/refman/5.7/en / ... TLDR: ALTER TABLE nom_table ENGINE = InnoDB;
Guilherme Vaz
En effet, c'était le cas dans ma base de données. J'ai décidé de changer le moteur MyISAM en InnoDB. Enfin, je peux travailler avec la base de données comme je le souhaite.
Mike
17

Vous obtenez cette erreur car il y a une valeur int table2.UserIDqui n'existe pas table1.UserID(je suppose que vous avez table2.UserIDdéfini la valeur manuellement avant de créer cette clé étrangère).
Un exemple pour cette scène: table1.UserIDobtenir les valeurs 1,2,3 et table2.UserIDobtenir les valeurs 4 (ajouter manuellement). Ainsi, lorsque vous créez une clé étrangère, ils ne peuvent pas trouver à UserID = 4partir de table1et l'erreur se produira.
Pour corriger cette erreur, supprimez simplement UserID = 4de table2ou vous pouvez vider les deux, puis créer la clé étrangère et.
Bonne chance!

Justin
la source
11

Cela m'a pris un certain temps à comprendre. En termes simples, la table qui fait référence à l'autre table contient déjà des données et une ou plusieurs de ses valeurs n'existent pas dans la table parent.

Par exemple, le tableau 2 contient les données suivantes:

UserID    PostID    Title    Summary
5         1         Lorem    Ipsum dolor sit

Tableau 1

UserID    Password    Username    Email
9         ********    JohnDoe     john@example.com

Si vous essayez d'ALTER table2 et ajoutez une clé étrangère, la requête échouera car UserID = 5 n'existe pas dans Table1.

Sbudah
la source
10

Si vous avez inséré une ligne dans la table 1 avant de créer la clé étrangère dans la table 2, vous obtiendrez une erreur de contrainte de clé étrangère, car la valeur d'incrémentation automatique est 2 dans la table 1 et 1 dans la table 2. Pour résoudre ce problème, vous devez tronquer la table 1 et remettre la valeur d'incrémentation automatique à 1. Vous pouvez ensuite ajouter la table 2.

Attaque
la source
10

Assurez-vous que vous avez défini le moteur de base de données sur InnoDB car dans MyISAM, la clé étrangère et la transaction ne sont pas prises en charge

Aman Maurya
la source
2
ALTER TABLE ma_table ENGINE = InnoDB;
Bishwas Mishra
7

Juste un petit correctif: faites le JoinColumn 'nullable = true' dans Table1 et le champ 'UserID' 'insertable = false' et 'nullable = true' dans Table2.

Dans l'entité Table1:

@OneToMany(targetEntity=Table2.class, cascade = CascadeType.ALL)
@JoinColumn(name = "UserID", referencedColumnName = "UserID", nullable = true)
private List<Table2> table2List;

Dans l'entité Table2:

@Column(insertable = false, nullable = true)
private int UserID;
Ujjwal Chaudhary
la source
Cette réponse a totalement résolu mon problème, merci beaucoup de partager cela. La clé pour moi était d'ajouter la @Column (insertable = false, nullable = true) sur le fichier que j'utilise comme clé foraeing dans mon objet / table enfant.
Israëlm
6

J'ai juste eu le même problème, la solution est simple.

Vous essayez d'ajouter un identifiant dans la table enfant qui n'existe pas dans la table parent.

vérifiez bien, car InnoDB a le bogue qui augmente parfois la colonne auto_increment sans ajouter de valeurs, par exemple, INSERT ... ON DUPLICATE KEY

Blaztix
la source
sérieusement? ne pas insérer une référence id qui n'existe pas ... il suffit de vérifier
Blaztix
5

J'ai eu un problème similaire. Vous essayez d'appliquer une clé étrangère sur une table qui a un contenu et la colonne ne peut pas être NULL. Vous avez deux options.

  1. Faites en sorte que la colonne à laquelle vous souhaitez appliquer des contraintes de clé étrangère soit Nullable. De cette façon, la clé étrangère s'appliquera sachant que certains champs peuvent être nullables. ( C'est ce que j'ai fait. )
  2. Créez la colonne à laquelle vous souhaitez appliquer la contrainte de clé étrangère, écrivez une requête pour insérer la clé étrangère dans la colonne, puis appliquez les contraintes de clé étrangère. ( Je n'ai pas essayé mais cela devrait fonctionner )
Jacob
la source
4

Assurez-vous que la valeur que vous insérez dans la clé étrangère existe dans la table parent. Cela m'a aidé. Par exemple, si vous insérez user_id = 2dans table.2, mais table.1que vous n'avez pas de user_id = 2, la contrainte générera une erreur. Le mien était le code d'erreur # 1452 pour être exact. J'espère que cela aide quelqu'un d'autre avec le même problème!

Dustin Hammack
la source
3

J'ai eu le même problème, et la raison en était que j'avais une ligne dans la première table avant d'ajouter la clé étrangère.

Ouissal
la source
1

J'ai également rencontré le même problème et le problème était que la valeur des entrées de ma table parent ne correspondait pas à la valeur de la table de clé étrangère. Veuillez donc essayer après avoir effacé toutes les lignes.

Justin José
la source
La contrainte exige que les utilisateurs référencés dans Table2 soient déjà définis dans Table1.
sorak
1

Au cas où les solutions fournies par d'autres ne fonctionnaient pas. Ensuite, vous devriez essayer de vérifier les moteurs de base de données des tables parent et enfant. Dans mon cas, j'ai réglé le moteur des tables parent sur "MyISAM", en le changeant en InnoDB le corrigeait.

J'espère que cela aidera les autres qui sont coincés comme moi.

Arun Shankar
la source
1

Vous ne devez pas placer un champ ondelete contre une cascade dans la base de données.

Définissez donc le champ onDelete sur RESTRICT

Bonne chance ♥

HamidReza Biglari
la source
0

Encore un autre cas étrange qui m'a donné cette erreur. J'avais référencé par erreur mes clés étrangères à la clé primaire id. Cela était dû à des commandes d'alter table incorrectes. J'ai découvert cela en interrogeant la table INFORMATION_SCHEMA (voir cette réponse stackoverflow)

La table était tellement confuse qu'elle ne pouvait être corrigée par aucune commande ALTER TABLE . J'ai finalement laissé tomber la table et l'ai reconstruite. Cela a éliminé intégritéError.

Vicky T
la source
0

Peut-être que pendant que vous avez ajouté la userIDcolonne, il y a une donnée pour cette certaine table qu'elle est établie afin qu'elle ait une valeur par défaut de 0, essayez d'ajouter la colonne sans leNOT NULL

WTFZane
la source
0

J'ai également eu cette erreur: "Impossible d'ajouter ou de mettre à jour une ligne enfant: une contrainte de clé étrangère échoue". J'ai eu l'erreur lors de l'ajout d'une nouvelle ligne à la table parent

Le problème était que la contrainte de clé étrangère avait été définie sur la table parent au lieu de la table enfant.

Nadir Latif
la source
0

Si vous utilisez un index mysql ou une relation entre les tables, vous supprimez d'abord les colonnes (par exemple: city_id) et créez de nouvelles colonnes avec le même nom (par exemple: city_id) .Ensuite, réessayez ...

Mahmut Aydın
la source
0

La table contient-elle des données existantes? Si tel est le cas, essayez d'effacer toutes les données de la table pour lesquelles vous souhaitez ajouter une clé étrangère. Ensuite, exécutez à nouveau le code (ajoutez une clé étrangère).

J'ai rencontré ce problème tant de fois. Cette suppression de toutes les données de la table fonctionne lorsque vous souhaitez ajouter une clé étrangère sur une table existante.

J'espère que cela fonctionne :)

Noldy
la source
0

Supprimez les index du champ UserID de table2. Il me convient

Anton
la source
0

Cette erreur se produit lorsque vous souhaitez ajouter une clé étrangère avec des valeurs qui n'existent pas dans la clé primaire de la table parent. Vous devez vous assurer que la nouvelle clé étrangère UserID dans table2 a des valeurs qui existent dans la clé primaire table1, parfois par défaut, elle est nulle ou égale à 0.

Vous pouvez d'abord mettre à jour tous les champs de la clé étrangère dans table2 avec une valeur qui existe dans la clé primaire de table1.

update table2 set UserID = 1 where UserID is null

Si vous souhaitez ajouter différents ID utilisateur, vous devez modifier chaque ligne avec les valeurs souhaitées.

Vladimir Salguero
la source
-1

La contrainte de clé étrangère de la table enfant échoue

Ce problème peut survenir pour les raisons suivantes:

Si vous le faites dans Spring mvc, vous devez décrire explicitement le type d'identifiant, car parfois mysql ne parvient pas à reconnaître le type d'identifiant. donc vous définissez explicitement comme dans les deux tables de votre classe d'entité@GeneratedValue (strategy = GenerationType.IDENTITY)

Qaiser Iqbal Moeeni
la source