【问题标题】:Dropping column with foreign key Laravel error: General error: 1025 Error on rename删除带有外键 Laravel 错误的列:一般错误:1025 重命名错误
【发布时间】:2015-01-26 08:30:29
【问题描述】:

我已经像这样使用迁移创建了一个表:

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');
    });
}

当我运行此迁移时,我收到以下错误:

[照亮\数据库\查询异常]
SQLSTATE [HY000]:一般错误:1025 重命名错误 './dev_iwms_reboot/despatch_discrepancies' 到 './dev_iwms_reboot/#sql2-67c-17c464' (errno: 152) (SQL: alter table despatch_discrepanciesdrop外键pick_detail_id)

[PDO异常]
SQLSTATE [HY000]:一般错误:1025 重命名错误 './dev_iwms_reboot/despatch_discrepancies' 到 './dev_iwms_reboot/#sql2-67c-17c464' (errno: 152)

当我尝试通过运行 php artisan migrate:rollback 命令来反转此迁移时,我收到了 Rolled back 消息,但它实际上并没有在数据库中执行任何操作。

知道可能出了什么问题吗?如何删除具有外键引用的列?

【问题讨论】:

    标签: php laravel laravel-4 database-migration


    【解决方案1】:

    你可以用这个:

    Schema::table('despatch_discrepancies', function (Blueprint $table) {
        $table->dropForeign(['pick_detail_id']);
        $table->dropColumn('pick_detail_id');
    });
    

    如果您在 dropForeign 源中达到峰值,如果您将列名作为数组传递,它将为您构建外键索引名称。

    【讨论】:

    • 接受的答案也有效:您必须使用正确的索引名称约定。但这也是该答案的问题:您必须记住索引的命名方案,而此解决方案会自动完成!我总是用另一种方式,总是抱怨它是多么不切实际。现在我立即切换到这个解决方案。非常感谢!
    • 很棒的把戏。我一直在做这件事,就像一个傻瓜。 Laravel 真的可以在文档上使用一些帮助。我可能会接受挑战...
    • 在 Laravel 5.0 中为我工作。非常感谢,亚历克斯!
    • 在 Laravel 5.2 中的工作就像一个魅力。
    • 这是一个巧妙的技巧。比记住外键命名约定(将来可能会改变)更友好。就像@ronin1184 所说,在 Laravel 5.2 中完美运行
    【解决方案2】:

    在 laravel 8 上使用 dropConstrainedForeignId (https://github.com/laravel/framework/pull/34806)

    <?php
    
    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;
    
    class AddAddressFieldsInEventTable extends Migration
    {
        /**
         * Run the migrations.
         *
         * @return void
         */
        public function up()
        {
            
            Schema::table('events', function (Blueprint $table) {
                $table->bigInteger('address_id')->nullable();
    
                $table->foreign('address_id')
                    ->references('id')
                    ->on('addresses')
                    ->onDelete('cascade');
            });
        }
    
        /**
         * Reverse the migrations.
         *
         * @return void
         */
        public function down()
        {
            Schema::table('events', function (Blueprint $table) {
                $table->dropConstrainedForeignId('address_id');
                $table->dropColumn('address_id');
            });
        }
    }
    
    

    【讨论】:

      【解决方案3】:

      你可以先禁用关系ID

      Schema::disableForeignKeyConstraints();
      

      【讨论】:

        【解决方案4】:

        我的表中有多个外键,然后我不得不通过在 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 不认为它们是我们要删除的单独列。所以我们只好一一丢掉。

        【讨论】:

        • 感谢我的朋友,在数组中添加列名对我有用。
        • 如果有人想知道,当列被删除时,MySQL 自动为外键创建的索引会被删除。无需使用 $table-&gt;dropIndex('column_name') 手动删除它们。
        • ty,我想要Schema::table('offices', function (Blueprint $table) {} 太糟糕了...
        • 由于某种原因,laravel 不在 dropForeign 中为表名添加前缀和后缀“foreign”。所以我认为应该是:$table-&gt;dropForeign(['offices_country_id_foreign']);
        【解决方案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 块需要进入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:refreshphp artisan migrate:reset 就可以解决问题了。

        【讨论】:

          【解决方案6】:

          解决这个问题的关键(对我来说)是确保 $table->dropForeign() 命令被传递了正确的关系名称,而不一定是列名称。您确实想要传递列名,恕我直言,这样会更直观。

          对我有用的是:

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

          所以我传递给对我有用的 dropForeign() 的字符串格式为:

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

          如果您可以使用 Sequel Pro 或 Navicat 之类的工具,那么能够将这些可视化将非常有帮助。

          【讨论】:

          • 这很好用,我只是发现它不像@Alex建议的那样用括号括起来那么直观。
          【解决方案7】:

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

          $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
          

          【讨论】:

          • 不适用于 Laravel 4.2。 不是键名的一部分。它仅适用于 __foreign。
          • 我在 laravel 4.2 中使用过它,现在仍然可以,它对我有用。
          • &lt;table_name&gt;_&lt;column_name&gt;_foreign 约定似乎仍然适用于 5.1
          • 显然,在删除关系约束后,您也必须删除列。我认为文档也应该包含这一点,因为人们很容易假设 dropForeign 也会删除该列。谢谢分享。 laravel.com/docs/5.0/schema#dropping-columns
          • 如果有人想知道,当列被删除时,MySQL 自动为外键创建的索引会被删除。无需使用$table-&gt;dropIndex('column_name') 手动删除它们。
          猜你喜欢
          • 2013-11-09
          • 1970-01-01
          • 2011-04-24
          • 2020-05-07
          • 1970-01-01
          • 2011-07-17
          • 2017-05-06
          • 2015-04-09
          • 2011-09-22
          相关资源
          最近更新 更多