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

199

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

Вот изображение моих связей в таблице, сгенерированное с помощью phpMyAdmin: Отношения

Я выполнил запрос 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

Было бы здорово, если бы кто-нибудь мог рассказать мне, что здесь происходит, у меня не было формального обучения или чего-то еще с MySQL:)

Спасибо.

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

ALTER TABLE sourcecodes_tags ADD FOREIGN KEY (sourcecode_id) REFERENCES sourcecodes (id) ON DELETE CASCADE ON UPDATE CASCADE
  • 2
    Не могли бы вы также опубликовать команду вставки / обновления, которая приводит к ошибке?
  • 63
    ваши таблицы пустые, когда вы добавляете этот внешний ключ?
Показать ещё 5 комментариев
Теги:
foreign-keys
mysql-error-1452

18 ответов

202

Скорее всего, ваша таблица 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;
  • 0
    UPDATE sourcecodes_tags SET sourcecode_id = NULL WHERE sourcecode_id NOT IN (SELECT id FROM sourcecodes) должен помочь избавиться от этих идентификаторов. Или, если null не разрешен в sourcecode_id , удалите эти строки или добавьте отсутствующие значения в таблицу sourcecodes .
  • 0
    Я думал о том же, но для меня SELECT Tchild.id FROM Tchild INNER JOIN Tmain ON Tmain.id = Tchild.fk_id WHERE Tmain.id IS NULL ничего не возвращает, поэтому проблема в другом месте!
Показать ещё 1 комментарий
87

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

mysql> SET foreign_key_checks = 0;

mysql> 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

mysql> SET foreign_key_checks = 1;
  • 45
    Foreign_key_checks есть по причине. Если вы не можете добавить внешний ключ, потому что он нарушает ограничение, вы должны сначала исправить данные. Отключение проверок и добавление ключа приводит вас в несогласованное состояние. Проверка внешнего ключа добавляет накладные расходы, если вы не хотите их использовать, используйте вместо этого myisam.
  • 4
    @AbuSadatMohammedYasin нет, это не должно: вопрос задан «что происходит», и этот ответ просто не пытается объяснить это. Как уже упоминалось cs_alumnus, есть большая проблема: все новые значения , которые должны быть ссылающимися другое значение в другой таблице ( в качестве внешнего ключа должны делать) могут указывать ничего, создавая несогласованное состояние. Краткое и эффективное объяснение Cayetano позволяет вам найти, какие значения вы должны обновить, прежде чем создавать ограничение, поэтому вы не будете удивлены запросами, которые должны возвращать значения, которые должны существовать!
52

Используйте 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, а также намного проще построить и повторить.

  • 1
    Итак, если я правильно понимаю, мы можем добавить внешний ключ в таблицу, в которой уже есть данные, но только если для каждой строки в родительской таблице существует дочерняя строка? Если для каждой строки в родительской таблице нет дочерних строк (что и обнаруживает ваш запрос), скрипт внешнего ключа завершится неудачно.
  • 0
    @ Vincent, если под родительской таблицей вы имеете в виду таблицу, на которую ссылаются, то да! Поэтому с помощью выбора Cayetano вы получаете все строки, которые необходимо обновить / удалить из вашей «дочерней» таблицы, прежде чем добавлять новое ограничение (FK). Как только они все указывают на значения в "another_table", тогда вы готовы!
23

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

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

  • 4
    Не нужно усекать все. "UPDATE sourcecodes_tags SET sourcecode_id = NULL WHERE sourcecode_id NOT IN (SELECT id FROM sourcecodes)" должно быть достаточно. Или, если null не разрешен в «sourcecode_id», удалите эти строки или добавьте отсутствующие значения в таблицу «sourcecodes».
  • 1
    Иногда, если данные увеличивают автоинкремент PK, это заставляет вас усекаться.
Показать ещё 4 комментария
14

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

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

SHOW TABLE STATUS WHERE Name =  't1';

ALTER TABLE t1 ENGINE=InnoDB;
  • 0
    Это решило это для меня, спасибо миллион
14

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

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

И теперь, когда я прочитал выражение nos, написал, что он проверяет.

13

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

  • Существуют ли какие-либо значения в вашем дочернем столбце, которые не существуют в родительском столбце (кроме NULL, если дочерний столбец имеет значение NULL)

  • У родительских и родительских столбцов одинаковый тип данных?

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

  • И это разрешило это для меня: обе таблицы имеют идентичную сортировку?

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

5
  • Удалите столбец, который вы хотите быть внешним ключом.

  • Создайте его еще раз, но установите его значение по умолчанию как NULL.

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

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

5

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

4

В итоге я удалю все данные в своей таблице и снова заново сработаю. Оно работает. Не блестящий, но это экономит много времени, особенно ваше приложение все еще находится на стадии разработки без каких-либо данных клиента.

2

попробуйте это

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

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

См. здесь пример: http://mstd.eu/index.php/2016/12/02/laravel-eloquent-integrity-constraint-violation-1452-foreign-key-constraint/

2

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

  • 0
    VHanded дал тот же ответ 3 года назад. Будем надеяться, что в таблицах не было важных данных ...
2

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

SELECT * FROM (tablename)
    WHERE (candidate key) <> (proposed foreign key value) 
        AND (candidate key) <> (next proposed foreign key value)

повторите AND (candidate key) <> (next proposed foreign key value) в вашем запросе для каждого значения внешнего ключа.

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

1

Я готовил эти решения, и этот пример может помочь.

В моей базе данных есть две таблицы (электронная почта и кредитная карточка) с первичными ключами для их идентификаторов. Другая таблица (клиент) ссылается на эти идентификаторы таблиц как внешние ключи. У меня есть причина, чтобы электронная почта была отделена от данных клиента.

Сначала я вставляю данные строки для ссылочных таблиц (email, credit_card), затем вы получаете идентификатор для каждого, эти идентификаторы необходимы в третьей таблице (клиенте).

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

Если вы сначала вставляете ссылочные строки для ссылочных таблиц, тогда строка, которая ссылается на внешние ключи, не возникает ошибка.

Надеюсь, что это поможет.

  • 0
    mysql> вставить в email (email) значения ('[email protected]'); mysql> вставить в значения ndtc (ndtc, year, month) ('1111222233334444', '2000', '01'); mysql> вставка в значения клиентов (nombres, apellidos, telefono, idNDTC, idEmail) («myname», «myapp», «5555555555», 1,1);
1

У меня есть решение, вам просто нужно ответить на один вопрос:

Ваша таблица уже хранит данные? В частности, таблица включала внешний ключ.

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

Удалить инструкцию: от дочернего элемента (который включает таблицу внешнего ключа) в родительскую таблицу.

Причина, по которой вы не можете добавить внешний ключ после ввода данных из-за несогласованности таблицы, что вы собираетесь использовать с новым внешним ключом в ранее заполненной таблице данных?

Если нет, следуйте другим инструкциям.

0

У меня была та же проблема и найдено решение, поместив NULL вместо NOT NULL в столбец внешнего ключа. Вот запрос:

ALTER TABLE `db`.`table1`
ADD COLUMN `col_table2_fk` INT UNSIGNED NULL,
ADD INDEX `col_table2_fk_idx` (`col_table2_fk` ASC),
ADD CONSTRAINT `col_table2_fk1`
FOREIGN KEY (`col_table2_fk`)
REFERENCES `db`.`table2` (`table2_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;

MySQL выполнил этот запрос!

0
UPDATE sourcecodes_tags
SET sourcecode_id = NULL
WHERE sourcecode_id NOT IN (
  SELECT id FROM sourcecodes);

должен помочь избавиться от этих идентификаторов. Или если null не разрешено в sourcecode_id, удалите эти строки или добавьте эти отсутствующие значения в таблицу sourcecodes.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню