Mysql ошибка 1452 - Не удается добавить или обновить дочернюю строку: ограничение внешнего ключа не удается - PullRequest
232 голосов
/ 10 августа 2009

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

Я выполнил запрос SHOW CREATE TABLE для обеих таблиц, sourcecodes_tags - это таблица с внешним ключом, sourcecodes - это ссылочная таблица.

CREATE TABLE `sourcecodes` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 `user_id` int(11) unsigned NOT NULL,
 `language_id` int(11) unsigned NOT NULL,
 `category_id` int(11) unsigned NOT NULL,
 `title` varchar(40) CHARACTER SET utf8 NOT NULL,
 `description` text CHARACTER SET utf8 NOT NULL,
 `views` int(11) unsigned NOT NULL,
 `downloads` int(11) unsigned NOT NULL,
 `time_posted` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 PRIMARY KEY (`id`),
 KEY `user_id` (`user_id`),
 KEY `language_id` (`language_id`),
 KEY `category_id` (`category_id`),
 CONSTRAINT `sourcecodes_ibfk_3` FOREIGN KEY (`language_id`) REFERENCES `languages` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
 CONSTRAINT `sourcecodes_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
 CONSTRAINT `sourcecodes_ibfk_2` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1

CREATE TABLE `sourcecodes_tags` (
 `sourcecode_id` int(11) unsigned NOT NULL,
 `tag_id` int(11) unsigned NOT NULL,
 KEY `sourcecode_id` (`sourcecode_id`),
 KEY `tag_id` (`tag_id`),
 CONSTRAINT `sourcecodes_tags_ibfk_1` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1

Это код, который генерирует ошибку:

ALTER TABLE sourcecodes_tags ADD FOREIGN KEY (sourcecode_id) REFERENCES sourcecodes (id) ON DELETE CASCADE ON UPDATE CASCADE

Ответы [ 20 ]

222 голосов
/ 10 августа 2009

Вполне вероятно, что ваша таблица sourcecodes_tags содержит sourcecode_id значений, которых больше нет в вашей таблице sourcecodes. Вы должны сначала избавиться от них.

Вот запрос, который может найти эти идентификаторы:

SELECT DISTINCT sourcecode_id FROM 
   sourcecodes_tags tags LEFT JOIN sourcecodes sc ON tags.sourcecode_id=sc.id 
WHERE sc.id IS NULL;
94 голосов
/ 04 февраля 2012

У меня была та же проблема с моей базой данных MySQL, но, наконец, я получил решение, которое сработало для меня.
Так как в моей таблице все было нормально с точки зрения mysql (обе таблицы должны использовать движок InnoDB, а тип данных каждого столбца должен быть одного типа, который принимает участие в ограничении внешнего ключа).
Единственное, что я сделал, - отключил проверку внешнего ключа, а затем включил ее после выполнения операции с внешним ключом.
Шаги, которые я предпринял:

SET foreign_key_checks = 0;
alter table tblUsedDestination add constraint f_operatorId foreign key(iOperatorId) references tblOperators (iOperatorId); Query
OK, 8 rows affected (0.23 sec) Records: 8  Duplicates: 0  Warnings: 0
SET foreign_key_checks = 1;
55 голосов
/ 01 июня 2011

Используйте NOT IN, чтобы найти ограничения , ограничивающие :

SELECT column FROM table WHERE column NOT IN 
(SELECT intended_foreign_key FROM another_table)

так, более конкретно:

SELECT sourcecode_id FROM sourcecodes_tags WHERE sourcecode_id NOT IN 
(SELECT id FROM sourcecodes)

EDIT: операторы IN и NOT IN, как известно, работают намного быстрее, чем операторы JOIN, а также намного проще в построении и повторении.

23 голосов
/ 29 мая 2013

Обрежьте таблицы и попробуйте добавить ограничение FK .

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

15 голосов
/ 29 марта 2013

Для меня эта проблема была немного другой и очень легко проверить и решить.

Вы должны убедиться, что ОБА ваших таблиц - InnoDB. Если одна из таблиц, а именно справочная таблица, является MyISAM, ограничение не будет выполнено.

    SHOW TABLE STATUS WHERE Name =  't1';

    ALTER TABLE t1 ENGINE=InnoDB;
14 голосов
/ 24 апреля 2013

У меня была такая же проблема сегодня. Я проверил четыре вещи, некоторые из которых уже упоминались здесь:

  1. Есть ли какие-либо значения в вашем дочернем столбце, которых нет в родительском столбце (кроме NULL, если дочерний столбец имеет значение NULL)

  2. Дочерний и родительский столбцы имеют одинаковый тип данных?

  3. Есть ли индекс в родительском столбце, на который вы ссылаетесь? MySQL, кажется, требует этого по соображениям производительности (http://dev.mysql.com/doc/refman/5.5/en/create-table-foreign-keys.html)

  4. И этот решил для меня: у обеих таблиц одинаковые параметры сортировки?

У меня был один стол в UTF-8, а другой в iso-что-то. Это не сработало. После изменения iso-таблицы на сопоставление UTF-8 ограничения могут быть добавлены без проблем. В моем случае phpMyAdmin даже не отображал дочернюю таблицу в iso-кодировке в раскрывающемся списке для создания ограничения внешнего ключа.

14 голосов
/ 22 октября 2011

Это также происходит при установке внешнего ключа для parent.id в child.column, если child.column уже имеет значение 0, а значение parent.id не равно 0

Вы должны убедиться, что каждый child.column имеет значение NULL или имеет значение, которое существует в parent.id

А теперь, когда я прочитал заявление, которое написал nos, это то, что он проверяет.

7 голосов
/ 13 августа 2015

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

Вы можете выполнить следующие действия:

  1. Удалить столбец, для которого вы пытались установить ограничение FK.

  2. Добавьте его еще раз и установите его значение по умолчанию как NULL.

  3. Попробуйте снова установить для него ограничение внешнего ключа.

5 голосов
/ 23 декабря 2012

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

4 голосов
/ 25 июля 2017

попробуйте

SET foreign_key_checks = 0;

ALTER TABLE sourcecodes_tags ADD FOREIGN KEY (sourcecode_id) REFERENCES sourcecodes (id) ON DELETE CASCADE ON UPDATE CASCADE

SET foreign_key_checks = 1;
...