使用外键Laravel错误删除列:常规错误:1025重命名时出错

时间:2014-11-27 17:03:42

标签: php laravel laravel-4 database-migration

我使用这样的迁移创建了一个表:

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并在sku列之后添加名为pick_id的新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');
    });
}

当我运行此迁移时,出现以下错误:

  

[照亮\数据库\ QueryException]
  SQLSTATE [HY000]:常规错误:1025重命名时出错   './dev_iwms_reboot/despatch_discrepancies'到   './dev_iwms_reboot/#sql2-67c-17c464'(错误号:152)(SQL:alter table   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消息,但它实际上并没有在数据库中执行任何操作。

知道可能出错的是什么?如何删除具有外键引用的列?

7 个答案:

答案 0 :(得分:113)

您可以使用:

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

如果你在dropForeign源代码中取得一个峰值,那么如果你将列名称作为数组传递,它将为你构建外键索引名称。

答案 1 :(得分:63)

事实证明;当你创建这样的外键时:

$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

答案 2 :(得分:13)

我的表中有多个外键,然后我必须通过在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不会将它们视为我们要删除的单独列。所以我们必须逐一删除它们。

答案 3 :(得分:10)

传递一个名为

的数组
$table->dropForeign(['user_id']);

答案 4 :(得分:9)

解决此问题的关键是确保$ table-&gt; dropForeign()命令传递正确的关系名称,而不一定是列名。你做想要传递列名,因为更直观的恕我直言。

对我有用的是:

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

因此我传递给dropForeign()的字符串的格式为:

[本地表格] _ [外键字段] _foreign

如果您可以访问Sequel Pro或Navicat等工具,那么能够对这些工具进行可视化非常有帮助。

答案 5 :(得分:4)

我遇到的事情是我不知道在哪里放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:refreshphp artisan migrate:reset就可以了。

答案 6 :(得分:0)

您可以先禁用关系 ID

Schema::disableForeignKeyConstraints();