次のような移行を使用してテーブルを作成しました。
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
を削除し、pick_id
列の後にsku
という新しいvarchar列を追加する必要があります。
そこで、次のような別の移行を作成しました。
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」への名前変更時のエラー(errno:152)(SQL:alter tabledespatch_discrepancies
drop外部キーpick_detail_id)[PDOException]
SQLSTATE [HY000]:一般エラー:1025 25
php artisan migrate:rollback
コマンドを実行してこの移行を逆にしようとすると、Rolled back
メッセージが表示されますが、実際にはデータベースで何もしていません。
何が間違っているのでしょうか?外部キー参照を持つ列をどのようにドロップしますか?
それが判明;このような外部キーを作成すると:
$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
これを使用できます:
$table->dropForeign(['pick_detail_id']);
$table->dropColumn('pick_detail_id');
DropForeignソースでピークを取る場合、列名を配列として渡すと、外部キーインデックス名が作成されます。
テーブルに複数の外部キーがあり、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は、削除したい個別の列を考慮しないためです。そのため、それらを1つずつドロップする必要があります。
列名で配列を渡す
$table->dropForeign(['user_id']);
これを解決するためのキー(私にとって)は、$ table-> dropForeign()コマンドに列名ではなく正しい関係名が渡されるようにすることでした。 notより直感的なIMHOのように、列名を渡したい場合。
私のために働いたのは:
$table->dropForeign('local_table_foreign_id_foreign');
$table->column('foreign_id');
だから、私のために働いたdropForeign()に渡した文字列は次の形式でした:
[ローカルテーブル] _[外部キーフィールド] _ foreign
Sequel ProやNavicatのようなツールにアクセスできる場合、それらを視覚化できると非常に役立ちます。
私が思いついたのは、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
ブロックは、lu_benefits_categories
移行のdown()
関数で、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
がトリックを行います。