Подтвердить что ты не робот

MySQL - невозможно добавить или обновить дочернюю строку: ограничение внешнего ключа не выполняется

Это, кажется, обычная ошибка, но для жизни меня я не могу понять этого.

У меня есть набор пользовательских таблиц InnoDB в MySQL, связанных друг с другом через внешний ключ; родительская таблица user и набор дочерних таблиц, которые хранят адреса электронной почты, действия и т.д. Все они привязаны к родительской таблице user внешним ключом uid со всеми родительскими и дочерними ключами int(10).

Все дочерние таблицы имеют значение uid с ограничением внешнего ключа, указывающим на user.uid, и установите ON DELETE CASCADE и ON UPDATE CASCADE.

Когда я удаляю пользователя из user, все дочерние ограниченные записи удаляются. Однако, когда я пытаюсь обновить значение user.uid, это приводит к следующей ошибке, а не к каскадированию изменения uid дочерних таблиц:

#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)

У меня такое чувство, что я должен упустить что-то очевидное здесь. Удаление ограничения ключа с помощью user_email и попытка обновления значения в user приводит к той же ошибке, но для следующей дочерней таблицы user в алфавитном порядке, поэтому я не верю, что это ошибка, связанная с таблицей.

EDIT:

Добавление результатов из 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
4b9b3361

Ответ 1

По несвязанной задаче я недавно поднял нашу базу данных MySQL в MySQL Workbench, а при просмотре табличных отношений для приведенных выше таблиц, я замеченные "дубликаты" и/или ложные отношения, которые я как-то пропустил раньше (они не появлялись в PHPMyAdmin FWIW). Удаление этих дополнительных отношений немедленно устранило проблему.

Ответ 2

Я решил, что мои проблемы с ограничениями внешнего ключа не удались, добавив следующий код в начало кода SQL (это было для импорта значений в таблицу)

SET @[email protected]@CHARACTER_SET_CLIENT;
SET @[email protected]@CHARACTER_SET_RESULTS;
SET @[email protected]@COLLATION_CONNECTION;
SET NAMES utf8;
SET @[email protected]@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @[email protected]@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @[email protected]@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO';
SET @[email protected]@SQL_NOTES, SQL_NOTES=0; 

Затем добавление этого кода в конец файла

SET [email protected]_SQL_MODE;
SET [email protected]_FOREIGN_KEY_CHECKS;
SET [email protected]_UNIQUE_CHECKS;
SET [email protected]_CHARACTER_SET_CLIENT;
SET [email protected]_CHARACTER_SET_RESULTS;
SET [email protected]_COLLATION_CONNECTION;
SET [email protected]_SQL_NOTES; 

Ответ 3

Поскольку вы не указали определения таблиц, трудно догадаться. Но похоже, что вы пытаетесь изменить внешний ключ в дочерней таблице. AFAIK, это незаконно, вы можете изменить его из родительского, но не дочерней таблицы.

Рассмотрим следующий пример:

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);

Тогда это разрешено:

UPDATE parent
  SET parent_id = 3 WHERE parent_id = 2;

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

Но это не так, потому что он изменяет родительский fk из дочерней таблицы:

UPDATE child1
  SET fk_parent_id = 4 WHERE fk_parent_id = 1;

Он получает ошибку, очень похожую на вашу ошибку:

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):

Ответ 4

Я столкнулся с такой же проблемой, создавая внешние ограничения для таблицы. простой способ выйти из этой проблемы - сначала взять резервную копию родительской и дочерней таблиц, а затем обрезать дочернюю таблицу и снова попытаться установить отношение. надеюсь, что это решит проблему.

Ответ 5

Такая ошибка при обновлении может быть вызвана различием в наборе символов и сопоставлении, поэтому убедитесь, что они одинаковы для обеих таблиц.

Ответ 6

Надеюсь, это поможет любому, кто имеет ту же ошибку, при импорте CSV-данных в связанные таблицы. В моем случае родительская таблица была в порядке, но я получил ошибку при импорте данных в дочернюю таблицу, содержащую внешний ключ. После временного удаления ограничения ключа foregn на дочерней таблице мне удалось импортировать данные и был удивлен, чтобы найти некоторые из значений в столбце FK со значениями 0 (очевидно, это вызвало ошибку, поскольку родительская таблица не имела такие значения в столбце PK). Дело в том, что данные в моей колонке CSV, предшествующие колонке FK, содержали запятые (которые я использовал в качестве полевого делиметра). Изменение разделителя для моего файла CSV решило проблему.