外部キーLaravelエラーのある列の削除:一般エラー:1025名前変更時のエラー


94

次のような移行を使用してテーブルを作成しました。

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を削除して、columnのsku後に呼び出される新しいvarchar列を追加する必要があり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');
    });
}

この移行を実行すると、次のエラーが発生します。

[Illuminate \ Database \ QueryException]
SQLSTATE [HY000]:一般エラー:1025「./ dev_iwms_reboot / despatch_discrepancies」の名前を「./dev_iwms_reboot/#sql2-67c-17c464」に変更するとエラーが発生します(エラー番号:152)(SQL:テーブルの変更 despatch_discrepancies外部キーを削除pick_detail_id)

[PDOException]
SQLSTATE [HY000]:一般エラー:1025「./ dev_iwms_reboot / despatch_discrepancies」の名前を「./dev_iwms_reboot/#sql2-67c-17c464」に変更するとエラーが発生します(エラー番号:152)

php artisan migrate:rollbackコマンドを実行してこの移行を元に戻そうとすると、Rolled backメッセージが表示されますが、実際にはデータベースで何も実行されていません。

何が間違っているのでしょうか?外部キー参照を持つ列をどのように削除しますか?

回答:


166

あなたはこれを使うことができます:

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

dropForeignソースでピークを迎える場合、列名を配列として渡すと、外部キーインデックス名が作成されます。


2
受け入れられた答えも機能します。正しいインデックス名の規則を使用する必要があります。しかし、これもその答えの問題です。このソリューションでは自動的に行われるのに対し、インデックスの命名スキームを覚えておく必要があります。私はいつも他の方法を使い、それがどれほど実用的でないかについていつも不平を言いました。今、私はすぐにこのソリューションに切り替えています。どうもありがとうございました!
マルコパランテ2015

6
素晴らしいトリック。私はそれを吸盤のように長い間やっています。Laravelは実際にドキュメントでいくつかのヘルプを使用できます。私が挑戦...取ること
simonhamp

1
Laravel5.0で働いてくれました。どうもありがとう、アレックス!
SilithCrowe 2016年

1
Laravel5.2ではチャームのように機能しました。
ronin1184 2016年

3
これは巧妙なトリックです。外部キーの命名規則(将来変更される可能性があります)を覚えるよりもはるかに友好的です。@ ronin1184が言ったように、Laravel 5.2で完全に機能します
Robin van Baalen 2016年

81

それが判明; このような外部キーを作成する場合:

$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

4
Laravel4.2では機能しません。<foreign_table_name>はキー名の一部ではありません。<table_name> _ <column_name> _foreignだけで機能します。
リッチリマー2015

私はlaravel4.2でそれを使用しましたが、それでも使用できます。
Latheesan 2015年

2
<table_name>_<column_name>_foreign大会はまだ5.1のために動作するようです
ヤヒヤウディン

どうやら、関係の制約を削除した後、列も削除する必要があります。dropForeignも列を削除すると簡単に推測できるため、ドキュメントにもそれを含める必要があったと思います。共有してくれてありがとう。laravel.com/docs/5.0/schema#dropping-columns
Picrasma

誰かが疑問に思っていた場合、MySQLが外部キー用に自動的に作成するインデックスは、列があるときに削除されます。を使用して手動でドロップする必要はありません$table->dropIndex('column_name')
アレクサンダー

24

テーブルに複数の外部キーがあり、downメソッドで配列のインデックスとして列名を渡すことにより、外部キー制約を1つずつ削除する必要がありました。

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は、削除する個別の列を考慮しないためです。だから私たちはそれらを一つずつ落とさなければなりません。


友人に感謝します。配列に列名を追加するとうまくいきます。
ピエール

誰かが疑問に思っていた場合、MySQLが外部キー用に自動的に作成するインデックスは、列があるときに削除されます。を使用して手動でドロップする必要はありません$table->dropIndex('column_name')
アレクサンダー

9

これを解決するための(私にとっての)鍵は、$ table-> dropForeign()コマンドに、必ずしも列名ではなく、正しい関係名が渡されていることを確認することでした。はるかに直感的なIMHOのように、列名を渡したくありません。

私のために働いたのは:

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

したがって、dropForeign()に渡した文字列は、次の形式でした。

[ローカルテーブル] _ [外部キーフィールド] _foreign

Sequel ProやNavicatなどのツールにアクセスできる場合は、それらを視覚化できると非常に役立ちます。


これは問題なく機能します。@ Alexが提案したように、テーブルを角かっこで囲むよりも直感的ではないことがわかりました。
マークカラバン2016年

5

私に起こったのは、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がトリックを行います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.