web-dev-qa-db-fra.com

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

Cela semble être une erreur commune, mais pour ma vie, je ne peux pas comprendre cela.

J'ai un ensemble de tables utilisateur InnoDB dans MySQL qui sont liées entre elles via une clé étrangère; la table parent user et un ensemble de tables enfants stockant des adresses de messagerie, des actions, etc. Elles sont toutes liées à la table parent user par une clé étrangère, uid, toutes les clés parent et enfant étant int(10).

Toutes les tables enfants ont une valeur uid avec une contrainte de clé étrangère pointant vers user.uid et définie sur ON DELETE CASCADE et ON UPDATE CASCADE

Lorsque je supprime un utilisateur de user, toutes les entrées d'enfants contraintes sont supprimées. Cependant, lorsque je tente de mettre à jour une valeur user.uid, l'erreur suivante est générée, plutôt que de transférer en cascade la modification uid aux tables enfants:

#1452 - Cannot add or update a child row: a foreign key constraint fails (`accounts`.`user_email`, CONSTRAINT `user_email_ibfk_2` FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON DELETE CASCADE ON UPDATE CASCADE)

J'ai le sentiment qu'il me manque quelque chose d'évident ici. Supprimer la contrainte de clé avec user_email et tenter de mettre à jour la valeur dans user entraîne la même erreur, mais pour la table enfant user alphabétique suivante, donc je ne crois pas qu'il s'agisse d'une erreur spécifique à la table.

MODIFIER:

Ajout dans les résultats de SHOW ENGINE INNODB STATUS:

------------------------
LATEST FOREIGN KEY ERROR
------------------------
121018 22:35:41 Transaction:
TRANSACTION 0 5564387, ACTIVE 0 sec, process no 1619, OS thread id 2957499248 updating or deleting, thread declared inside InnoDB 499
mysql tables in use 1, locked 1
17 lock struct(s), heap size 2496, 9 row lock(s), undo log entries 2
MySQL thread id 3435659, query id 24068634 localhost root Updating
UPDATE `accounts`.`user` SET `uid` = '1' WHERE `user`.`uid` = 306
Foreign key constraint fails for table `accounts`.`user_email`:
,
  CONSTRAINT `user_email_ibfk_2` FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON DELETE CASCADE ON UPDATE CASCADE
Trying to add in child table, in index `uid` Tuple:
DATA Tuple: 2 fields;
...
A bunch of hex code

But in parent table `accounts`.`user`, in index `PRIMARY`,
the closest match we can find is record:
...
A bunch of hex code
15
Paul Mennega

Dans une tâche indépendante, j’ai récemment évoqué notre base de données MySQL dans MySQL Workbench , et lors de l’affichage des relations entre les tables ci-dessus, j’ai remarqué des relations «en double» et/ou erronées que pas dans PHPMyAdmin FWIW). La suppression de ces relations supplémentaires a éclairci le problème immédiatement.

1
Paul Mennega

J'ai résolu mes problèmes ' de clé étrangère qui échouaient ' en ajoutant le code suivant au début du code SQL (il s'agissait de l'importation de valeurs dans une table)

SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT;
SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS;
SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION;
SET NAMES utf8;
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO';
SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0; 

Puis en ajoutant ce code à la fin du fichier

SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT;
SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS;
SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION;
SET SQL_NOTES=@OLD_SQL_NOTES; 
11
Sidupac

Puisque vous n'avez pas donné de définitions de table, c'est difficile à deviner. Mais il semble que vous tentiez de modifier la clé étrangère dans la table enfant. Autant que je sache, c'est illégal, vous pouvez le modifier depuis le parent, mais pas la table enfant.

Considérons cet exemple:

CREATE TABLE parent (
  parent_id INT NOT NULL,
  parent_data int,

  PRIMARY KEY (parent_id)
) ENGINE=INNODB;

CREATE TABLE child1 (
  child1_id INT,
  child1_data INT,
  fk_parent_id INT,

  INDEX par_ind1 (fk_parent_id),

  FOREIGN KEY (fk_parent_id)
    REFERENCES parent(parent_id)
    ON DELETE CASCADE
    ON UPDATE CASCADE
) ENGINE=INNODB;

CREATE TABLE child2 (
  child2_id INT,
  child2_data INT,
  fk_parent_id INT,

  INDEX par_ind2 (fk_parent_id),

  FOREIGN KEY (fk_parent_id)
    REFERENCES parent(parent_id)
    ON DELETE CASCADE
    ON UPDATE CASCADE
) ENGINE=INNODB;

INSERT INTO parent
  (parent_id, parent_data)
  VALUES
  (1, 11),
  (2, 12);

INSERT INTO child1
  (child1_id, child1_data, fk_parent_id)
  VALUES
  (101, 1001, 1),
  (102, 1002, 1),
  (103, 1003, 1),
  (104, 1004, 2),
  (105, 1005, 2);

INSERT INTO child2
  (child2_id, child2_data, fk_parent_id)
  VALUES
  (106, 1006, 1),
  (107, 1007, 1),
  (108, 1008, 1),
  (109, 1009, 2),
  (110, 1010, 2);

Alors ceci est permis:

UPDATE parent
  SET parent_id = 3 WHERE parent_id = 2;

SELECT * FROM parent;
SELECT * FROM child1;
SELECT * FROM child2;

Mais ce n'est pas le cas, car cela modifie le fk parent de la table enfant:

UPDATE child1
  SET fk_parent_id = 4 WHERE fk_parent_id = 1;

Il obtient une erreur très similaire à votre erreur:

Cannot add or update a child row: a foreign key constraint fails (`db_2_b43a7`.`child1`, CONSTRAINT `child1_ibfk_1` FOREIGN KEY (`fk_parent_id`) REFERENCES `parent` (`parent_id`) ON DELETE CASCADE ON UPDATE CASCADE):
8
walrii

J'avais affronté le même problème en créant des contraintes étrangères sur la table. Le moyen le plus simple de résoudre ce problème consiste à commencer par sauvegarder la table parent et la table enfant, puis à la tronquer, puis à essayer de créer une relation. espérons que cela résoudra le problème.

4
Varun

Une telle erreur lors de la mise à jour peut être due à la différence entre le jeu de caractères et le classement. Assurez-vous donc qu'ils sont identiques pour les deux tables.

1
Anna