Удаление столбца с внешним ключом Ошибка Laravel: Общая ошибка: Ошибка 1025 при переименовании


Я создал таблицу, используя миграцию следующим образом:

public function up()
{
    Schema::create('despatch_discrepancies',  function($table) {
        $table->increments('id')->unsigned();
        $table->integer('pick_id')->unsigned();
        $table->foreign('pick_id')->references('id')->on('picks');
        $table->integer('pick_detail_id')->unsigned();
        $table->foreign('pick_detail_id')->references('id')->on('pick_details');
        $table->integer('original_qty')->unsigned();
        $table->integer('shipped_qty')->unsigned();
    });
}

public function down()
{
    Schema::drop('despatch_discrepancies');
}

Мне нужно изменить эту таблицу и удалить ссылку на внешний ключ и столбец pick_detail_id и добавить новый столбец varchar с именем sku после столбца pick_id.

Итак, я создал еще одну миграцию, которая выглядит так:

public function up()
{
    Schema::table('despatch_discrepancies', function($table)
    {
        $table->dropForeign('pick_detail_id');
        $table->dropColumn('pick_detail_id');
        $table->string('sku', 20)->after('pick_id');
    });
}

public function down()
{
    Schema::table('despatch_discrepancies', function($table)
    {
        $table->integer('pick_detail_id')->unsigned();
        $table->foreign('pick_detail_id')->references('id')->on('pick_details');
        $table->dropColumn('sku');
    });
}

Когда я запускаю эту миграцию, я получаю следующую ошибку:

[Осветить\База данных\Исключение запроса]
SQLSTATE[HY000]: Общая ошибка: Ошибка 1025 при переименовании './dev_iwms_reboot/отправка_дискрепанаций' в './dev_iwms_reboot/#sql2-67c-17c464' (ошибка: 152) (SQL: изменить таблицу despatch_discrepancies удалить внешний ключ pick_detail_id)

[Исключение PDO]
SQLSTATE[HY000]: Общая ошибка: 1025 Ошибка при переименовании './dev_iwms_reboot/dispatch_discrepancies' в './dev_iwms_reboot/#sql2-67c-17c464' (ошибка: 152)

Когда я пытаюсь отменить эту миграцию, выполнив команду php artisan migrate:rollback, я получаю сообщение Rolled back, но на самом деле оно ничего не делает в база данных.

Есть идеи, что может быть не так? Как удалить столбец, содержащий ссылку на внешний ключ?

Author: Latheesan, 2014-11-27

6 answers

Вы можете использовать это:

$table->dropForeign(['pick_detail_id']);
$table->dropColumn('pick_detail_id');

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

 89
Author: Alex Pineda, 2015-05-11 20:55:00

Получается; когда вы создаете внешний ключ вот так:

$table->integer('pick_detail_id')->unsigned();
$table->foreign('pick_detail_id')->references('id')->on('pick_details');

Laravel однозначно называет ссылку на внешний ключ следующим образом:

<table_name>_<foreign_table_name>_<column_name>_foreign
despatch_discrepancies_pick_detail_id_foreign (in my case)

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

$table->dropForeign('despatch_discrepancies_pick_detail_id_foreign');
$table->dropColumn('pick_detail_id');

Обновление:

Laravel 4.2+ вводит новое соглашение об именовании:

<table_name>_<column_name>_foreign
 59
Author: Latheesan, 2015-06-25 10:43:25

Ключом (для меня) к решению этой проблемы было убедиться, что команде $table->dropforeign() передается правильное имя связи, а не обязательно имя столбца. Вы не хотите передавать имя столбца, как было бы гораздо более интуитивно понятным ИМХО.

Что сработало для меня, так это:

$table->dropForeign('local_table_foreign_id_foreign');
$table->column('foreign_id');

Таким образом, строка, которую я передал в dropForeign(), которая работала для меня, была в формате:

[ локальная таблица]_[ поле внешнего ключа]_foreign

Если у вас есть доступ к таким инструментам, как Sequel Pro или Navicat, возможность их визуализации будет очень полезна.

 8
Author: DirtyBirdNJ, 2016-05-13 06:40:53

Передайте массив с именем col

$table->dropForeign(['user_id']);
 8
Author: Harry Bosh, 2017-02-17 23:11:05

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

public function up()
{
    Schema::table('offices', function (Blueprint $table) {
        $table->unsignedInteger('country_id')->nullable();
        $table->foreign('country_id')
            ->references('id')
            ->on('countries')
            ->onDelete('cascade');

        $table->unsignedInteger('stateprovince_id')->nullable();
        $table->foreign('stateprovince_id')
            ->references('id')
            ->on('stateprovince')
            ->onDelete('cascade');
        $table->unsignedInteger('city_id')->nullable();
        $table->foreign('city_id')
            ->references('id')
            ->on('cities')
            ->onDelete('cascade');
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::table('offices', function (Blueprint $table) {
        $table->dropForeign(['country_id']);
        $table->dropForeign(['stateprovince_id']);
        $table->dropForeign(['city_id']);
        $table->dropColumn(['country_id','stateprovince_id','city_id']);
    });
} 

Использование приведенного ниже оператора не работает

$table->dropForeign(['country_id','stateprovince_id','city_id']); 

Потому что dropForeign не считает их отдельными столбцами, которые мы хотим удалить. Поэтому мы должны отбросить их одного за другим.

 5
Author: Afraz Ahmad, 2018-04-03 08:56:02

Мне пришло в голову, что я не знал, куда поставить блок Schema::table.

Позже я обнаружил, что ключ находится в ошибке SQL:

[Illuminate\Database\QueryException]
SQLSTATE[23000]: Integrity constraint violation: 1217 Cannot delete or update a parent row: a foreign key constraint fails (SQL: drop table if exists `lu_benefits_categories`)

Таким образом, блок Schema::table должен входить в функцию down() миграции lu_benefits_categories и перед строкой Schema::dropIfExists:

public function down()
{
    Schema::table('table', function (Blueprint $table) {
        $table->dropForeign('table_category_id_foreign');
        $table->dropColumn('category_id');
    });
    Schema::dropIfExists('lu_benefits_categories');
}

После этого php artisan migrate:refresh или php artisan migrate:reset сделают свое дело.

 4
Author: Gus, 2017-03-15 23:29:13