# Проблема
Попытка добавить внешний ключ к таблице приводит к одной из ошибок:
General error: 1215 Cannot add foreign key constraint
General error: 3780 Referencing column 'post_id' and referenced column 'id' in foreign key constraint 'xxx' are incompatible
General error: 1824 Failed to open the referenced table
General error: 3730 Cannot drop table 'xxx' referenced by a foreign key constraint
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails
Все требования к механизму внешних ключей можно найти в
документации
Далее рассмотрим самые популярные причины.
# Разные типы полей
Столбцы должно быть одного типа, а для INTEGER или DECIMAL ещё и одного размера.
General error: 3780 Referencing column 'post_id' and referenced column 'id' in foreign key constraint 'xxx' are incompatible
Обычно внешний ключ ссылается на ID другой таблицы и по умолчанию тип ID: UNSIGNED BIG INTEGER
1Schema::create('comments', function (Blueprint $table) {2 $table->id();3 4 $table->bigInteger('post_id')->unsigned();5 $table->foreign('post_id')->references('id')->on('posts');6});
Или начиная с 7 версии более лаконичный синтаксис, который создаёт колонку и ключ:
1Schema::create('comments', function (Blueprint $table) {2 $table->id();3 4 $table->foreignId('post_id')->constrained();5});
Обрати внимание, что в старых версиях по умолчанию тип ID был UNSIGNED INTEGER
# Порядок миграций
Логично, что прежде чем ссылаться на таблицу она уже должна быть создана, тем не менее это часто упускается из виду и сначала создаётся "дочерняя" таблица.
General error: 1824 Failed to open the referenced table
Не всегда ошибка говорит, что не так и может быть общей: Cannot add foreign key constraint
# Данные в таблице
Таблица уже содержит невалидные значения. Вариант часто встречается, когда внешний ключ добавляется на уже созданную таблицу в которой есть данные.
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails
Ошибка говорит о том, что нельзя добавить ключ, т.к. данные не консистентные. Проблему необходимо устранить вручную установив правильные значения или NULL
Ещё один вариант происходит при откате миграций:
General error: 3730 Cannot drop table 'xxx' referenced by a foreign key constraint
Причина часто в нарушенном порядке миграций или проблемах в down(). Если ошибка происходит при php artisan migrate:fresh, то необходимо вручную удалять таблицы или данные в них.
# Движок таблиц
Родительская таблица не InnoDB. MyISAM не поддерживает внешние ключи.