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

Я пытаюсь запустить миграцию для таблицы inventories, которую я создал с помощью этой миграции:

Schema::create('inventories', function (Blueprint $table) {
    $table->increments('id');
    $table->integer('remote_id')->unsigned();
    $table->integer('local_id')->unsigned();
    $table->string('local_type');
    $table->string('url')->nullable()->unique();
    $table->timestamps();
});

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

Schema::table('inventories', function (Blueprint $table) {
    $table->foreign('local_id')->references('id')->on('contents')->onDelete('cascade');
});

Но при попытке запустить миграцию я получаю сообщение об ошибке:

[Освещение \ База данных \ QueryException]

SQLSTATE [23000]: нарушение ограничения целостности: 1452 Невозможно добавить или обновить дочернюю строку: ограничение внешнего ключа не выполнено (middleton
.#sql-5d6_162a, CONSTRAINT inventories_local_id_foreign FOREIGN KEY (local_id) ССЫЛКИ contents (id) ПРИ КАСКАДЕ УДАЛЕНИЯ) (SQL: изменить таблицу inventories добавить ограничение inventories_local_id_foreign ссылки на внешний ключ (local_id) contents (id) при каскаде удаления)

[PDOException]

SQLSTATE [23000]: нарушение ограничения целостности: 1452 Невозможно добавить или обновить дочернюю строку: ограничение внешнего ключа не выполнено (middleton
.#sql-5d6_162a, CONSTRAINT inventories_local_id_foreign FOREIGN KEY (local_id) ССЫЛКИ contents (id) ПРИ КАСКАДЕ УДАЛЕНИЯ)

Что я делаю неправильно?


person Leff    schedule 13.11.2017    source источник


Ответы (2)


Вероятно, у вас есть записи в таблице inventories с local_id, которым не соответствует id в таблице contents, отсюда и ошибка. Вы можете решить эту проблему одним из двух способов:

  • Запустите миграцию с выключенным foreign_key_checks. Это отключит ограничения внешнего ключа для существующих строк (если вы этого хотите). Это задокументировано здесь
  • Вставляйте только те записи, которым соответствует поле id в contents таблице. Вы можете использовать INSERT INTO.. WHERE EXISTS запрос, чтобы отфильтровать записи и вставить только эти записи.
person Darshan Mehta    schedule 13.11.2017
comment
Да, как только я удалил все таблицы и запустил все миграции сразу, все заработало. Спасибо - person Leff; 13.11.2017

У меня такая же проблема. Исправлено добавлением nullable в поле:

Schema::create('table_name', function (Blueprint $table) {
    ...
    $table->integer('some_id')->unsigned()->nullable();
    $table->foreign('some_id')->references('id')->on('other_table');
    ...
});

Обратите внимание, что после миграции все существующие строки будут иметь some_id = NULL.

UPD:

Начиная с Laravel 7, есть более короткий способ сделать то же самое:

$table->foreignId('some_id')->nullable()->constrained();

Также очень важно, чтобы nullable был ДО constrained.

Дополнительную информацию можно найти здесь, в официальной документации

person Roman Meyer    schedule 23.07.2018
comment
Это важно помнить для существующих баз данных, спасибо, что пробудили мою память! - person Andrew Fox; 14.01.2021