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

174

Таблица 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   |     |         |                |
+----------+-------------+------+-----+---------+----------------+

Таблица 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   |     |         |                |
+------------------+--------------+------+-----+---------+----------------+

Ошибка:

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

Что я сделал не так? Я читаю http://www.w3schools.com/Sql/sql_foreignkey.asp и не вижу, что не так.

Том
источник
4
Можете ли вы опубликовать запрос, который вызывает ошибку?
влажный
38
В двух словах, вы пытаетесь вставить / обновить значение table2.UserID, которого нет в table1.UserID.
Джо Стефанелли
Не знаю почему, но после перемещения моей базы данных из среды Windows в Linux мне пришлось удалить и воссоздать отношение (именно тогда я заметил проблему). Значение существовало, но удаление и повторное добавление отношения исправили его. Возможно, вам нужно быть очень осторожным, делая это, очевидно.
Johnsnails

Ответы:

235

Вы получаете эту ошибку, потому что вы пытаетесь добавить / обновить строку table2, у которой нет действительного значения для UserIDполя на основе значений, в настоящее время хранящихся в table1. Если вы отправите еще немного кода, я могу помочь вам диагностировать конкретную причину.

Брайан Дрисколл
источник
PreparedStatement st = connection.prepareStatement («Вставить в таблицу 2 (UserID, PostID, Title, Summary)« + »значения (UserID,?,?,?)");
Том
15
не уверен, для чего понижатель; мой ответ совершенно верный и правильный.
Брайан Дрисколл
Хм ... определенно не стоит смешивать именованные параметры с неназванными параметрами в подготовленном вами утверждении. это должны быть значения (?,?,?,?) с соответствующим значением для UserID, указанным в вашем операторе execute.
Брайан Дрисколл
Так что мне нужно сделать с другим оператором SQL, чтобы получить идентификатор пользователя из таблицы1?
Том
5
Скорее всего, 0, замените его на Null, если это так
Джеффри Николсон Карре
123

Это означает , что вы пытаетесь вставить table2в UserIDзначение , которое не существует в table1.

Рами С
источник
104

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

SET FOREIGN_KEY_CHECKS=0

Это отключит сопоставление внешнего ключа с любыми другими таблицами. После того, как вы закончите с таблицей, включите его снова

SET FOREIGN_KEY_CHECKS=1

Это работает для меня много раз.

Сандип Гири
источник
Как я это использую ??
Сачин из Пуне
2
@SachinfromPune просто добавьте SET FOREIGN_KEY_CHECKS = 0; при запуске файла mysql и SET FOREIGN_KEY_CHECKS = 1; в конце файла mysql
переимпортируйте
1
Разве это не проблематично? Вы теряете ссылочную целостность, верно?
roadrunner66
Ссылочная целостность поддерживается наличием правильных записей индекса. Если у вас есть правильные ключи и индексы, вы сможете отключить проверку ключей во время массового ввода.
Вернон Кинан
46

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

Смотрите http://nick.zoic.org/art/mysql-foreign-key-error/

NickZoic
источник
1
Да, у меня такая же проблема. Две таблицы должны быть InnoDB!
Изумрудное
2
У меня была такая же проблема, спасибо за совет. Вот ссылка на документацию MySQL о том, как преобразовать таблицы из MyISAM в InnoDB dev.mysql.com/doc/refman/5.7/en/… TLDR: ALTER TABLE table_name ENGINE = InnoDB;
Гильерме Ваз
Действительно, так было в моей базе данных. Я решил изменить движок MyISAM на InnoDB. Наконец, я могу работать с базой данных так, как я хотел.
Майк
17

Вы получаете эту ошибку, потому что есть некоторое значение int table2.UserID, которого не существует table1.UserID(я полагаю, что вы установили table2.UserIDзначение вручную до того, как создали этот внешний ключ).
Один пример для этой сцены: table1.UserIDполучить значения 1,2,3 и table2.UserIDполучить значения 4 (добавить вручную). Поэтому , когда вы делаете внешний ключ, они не могут найти UserID = 4из table1и ошибка будет ocurse.
Чтобы исправить эту ошибку, просто удалите UserID = 4из table2или вы можете очистить их обоих, а затем создать внешний ключ и.
Удачи!

Джастин
источник
11

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

например, Таблица2 имеет следующие данные:

UserID    PostID    Title    Summary
5         1         Lorem    Ipsum dolor sit

Таблица 1

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

Если вы попытаетесь изменить таблицу 2 и добавить внешний ключ, тогда запрос не будет выполнен, поскольку UserID = 5 не существует в таблице Table1.

Sbudah
источник
10

Если вы вставили строку в таблицу 1 до создания внешнего ключа в таблице 2, вы получите ошибку ограничения внешнего ключа, поскольку значение автоматического увеличения равно 2 в таблице 1 и 1 в таблице 2. Чтобы решить эту проблему, необходимо выполнить следующие действия. обрежьте таблицу 1 и установите значение автоматического приращения обратно в 1. Затем вы можете добавить таблицу 2.

Attaque
источник
10

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

Аман Маурья
источник
2
ALTER TABLE my_table ENGINE = InnoDB;
Бишвис Мишра
7

Немного исправлено: сделайте JoinColumn 'nullable = true' в Таблице 1 и поле 'UserID', вставьте = false 'и' nullable = true 'в Таблице 2.

В Table1 Entity:

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

В Table2 Entity:

@Column(insertable = false, nullable = true)
private int UserID;
Уджвал Чаудхари
источник
Этот ответ полностью решил мою проблему, большое спасибо за то, что поделились этим. Ключом для меня было добавление @Column (inserttable = false, nullable = true) в поле, которое я использую в качестве ключа для поиска в моем дочернем объекте / таблице.
Исраэль
6

У меня просто была такая же проблема, решение легко.

Вы пытаетесь добавить идентификатор в дочернюю таблицу, который не существует в родительской таблице.

проверьте хорошо, потому что InnoDB имеет ошибку, которая иногда увеличивает столбец auto_increment без добавления значений, например, INSERT ... ON DUPLICATE KEY

Blaztix
источник
шутки в сторону? не вставляйте идентификационную ссылку, которая не существует ... просто проверьте
Blaztix
5

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

  1. Сделайте столбец, к которому вы хотите применить ограничения внешнего ключа, обнуляемым. Таким образом, внешний ключ будет применяться, зная, что некоторые поля могут быть обнуляемыми. ( Это то, что я сделал. )
  2. Создайте столбец, к которому вы хотите применить ограничение внешнего ключа, напишите запрос, чтобы вставить внешний ключ в столбец, а затем примените ограничения внешнего ключа. ( Не пробовал, но это должно работать )
Иаков
источник
4

Убедитесь, что значение, которое вы вставляете во внешний ключ, существует в родительской таблице. Это помогло мне. Например , если вставить user_id = 2в table.2, но table.1не имеет user_id = 2, то ограничение будет выдавать ошибку. Мой был код ошибки # 1452, если быть точным. Надеюсь, что это поможет кому-то еще с той же проблемой!

Дастин Гамак
источник
3

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

Ouissal
источник
1

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

Джастин хосе
источник
Ограничение требует, чтобы пользователи, указанные в Таблице 2, уже были определены в Таблице 1.
Сорак
1

В случае, если решения, предоставленные другими, не сработали. Затем вы должны попытаться проверить движки баз данных родительской и дочерней таблиц. В моем случае я установил для движка родительских таблиц «MyISAM», изменив его на InnoDB, и исправил.

Надеюсь, что это помогает другим, которые застряли как я.

Арун Шанкар
источник
1

Вы не должны помещать поле ondelete против каскада в базе данных.

Так что установите поле onDelete для RESTRICT

Удачи ♥

ХамидРеза Биглари
источник
0

Еще один странный случай, который дал мне эту ошибку. Я ошибочно связал свои внешние ключи с первичным ключом id. Это было вызвано неправильными командами alter table. Я узнал об этом, запросив таблицу INFORMATION_SCHEMA (см. Этот ответ по стеку)

Таблица была настолько запутана, что не могла быть исправлена ​​никакими командами ALTER TABLE . Я наконец уронил стол и восстановил его. Это избавило от ошибки целостности.

Вики Т
источник
0

Может быть, пока вы добавили userIDстолбец, для этой определенной таблицы есть данные, для которых она установлена, поэтому она будет иметь значение по умолчанию 0, попробуйте добавить столбец безNOT NULL

WTFZane
источник
0

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

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

Надир Латиф
источник
0

Если вы используете mysql индекс или отношение между таблицами, сначала вы удаляете столбцы (например, city_id) и создаете новые столбцы с тем же именем (например, city_id). Затем повторите попытку ...

Махмут Айдын
источник
0

Существуют ли какие-либо данные, содержащиеся в таблице? Если это так, попробуйте очистить все данные в таблице, в которую вы хотите добавить внешний ключ. Затем снова запустите код (добавьте внешний ключ).

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

Надеюсь, это работает :)

Noldy
источник
0

Удалите индексы из поля UserID таблицы 2. Его костюмы для меня

Антон
источник
0

Эта ошибка возникает, когда вы хотите добавить внешний ключ со значениями, которых нет в первичном ключе родительской таблицы. Вы должны быть уверены, что новый внешний ключ UserID в table2 имеет значения, которые существуют в первичном ключе table1, иногда по умолчанию он равен нулю или равен 0.

Сначала вы можете обновить все поля внешнего ключа в таблице2, указав значение, которое существует в первичном ключе таблицы1.

update table2 set UserID = 1 where UserID is null

Если вы хотите добавить разные идентификаторы пользователей, вы должны изменить в каждой строке нужные значения.

Владимир Салгуэро
источник
-1

Сбой ограничения внешнего ключа дочерней таблицы

Эта проблема может возникнуть по следующей причине:

Если вы делаете это в Spring mvc, вам нужно явно описать тип id, потому что иногда mysql не может распознать тип id. так что вы явно установите, как в обеих таблицах в вашем классе сущности@GeneratedValue (strategy = GenerationType.IDENTITY)

Кайзер Икбаль Моини
источник