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

Lat*_*san 69 php database-migration laravel laravel-4

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

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');
}
Run Code Online (Sandbox Code Playgroud)

我需要更改此表并删除外键引用和列,pick_detail_id并添加一个名为skuafter pick_idcolumn 的新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');
    });
}
Run Code Online (Sandbox Code Playgroud)

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

[Illuminate\Database\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消息,但它实际上并没有在数据库中执行任何操作.

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

Ale*_*eda 128

你可以用这个:

$table->dropForeign(['pick_detail_id']);
$table->dropColumn('pick_detail_id');
Run Code Online (Sandbox Code Playgroud)

如果在dropForeign源处获取峰值,则在将列名称作为数组传递时,它将为您构建外键索引名称.

  • 太棒了.我一直在像吸盘一样长途跋涉.Laravel真的可以在文档上使用一些帮助.我可能会接受挑战...... (6认同)
  • 这个数组技巧不在文档中.谢谢! (4认同)
  • 这是一个巧妙的伎俩.比记住外键命名约定(将来可能会改变)更友好.就像@ ronin1184所说,在Laravel 5.2中完美运行 (3认同)
  • 接受的答案也有效:您必须使用正确的索引名称约定.但这也是答案的问题:你必须记住索引的命名方案,而这个解决方案自动完成!我总是用另一种方式,总是抱怨它是多么不实用.现在我立即转向这个解决方案.非常感谢你! (2认同)

Lat*_*san 70

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

$table->integer('pick_detail_id')->unsigned();
$table->foreign('pick_detail_id')->references('id')->on('pick_details');
Run Code Online (Sandbox Code Playgroud)

Laravel唯一地命名外键引用,如下所示:

<table_name>_<foreign_table_name>_<column_name>_foreign
despatch_discrepancies_pick_detail_id_foreign (in my case)
Run Code Online (Sandbox Code Playgroud)

因此,当您想要删除具有外键引用的列时,您必须这样做:

$table->dropForeign('despatch_discrepancies_pick_detail_id_foreign');
$table->dropColumn('pick_detail_id');
Run Code Online (Sandbox Code Playgroud)

更新:

Laravel 4.2+引入了一个新的命名约定:

<table_name>_<column_name>_foreign
Run Code Online (Sandbox Code Playgroud)

  • 在Laravel 4.2中不起作用.<foreign_table_name>不是密钥名称的一部分.它只适用于<table_name> _ <column_name> _foreign. (4认同)
  • `<table_name> _ <column_name> _foreign`约定似乎仍然适用于5.1 (2认同)

Afr*_*mad 17

我在表中有多个外键,然后我必须通过在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']);
    });
} 
Run Code Online (Sandbox Code Playgroud)

使用以下语句不起作用

$table->dropForeign(['country_id','stateprovince_id','city_id']); 
Run Code Online (Sandbox Code Playgroud)

因为dropForeign不会将它们视为我们要删除的单独列.所以我们必须逐一删除它们.


Har*_*osh 12

传递一个带有col名称的数组

$table->dropForeign(['user_id']);
Run Code Online (Sandbox Code Playgroud)


Dir*_*dNJ 9

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

对我有用的是:

$table->dropForeign('local_table_foreign_id_foreign');
$table->column('foreign_id');
Run Code Online (Sandbox Code Playgroud)

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

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

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


Fil*_*ano 7

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

Run Code Online (Sandbox Code Playgroud)


Gus*_*Gus 6

我突然想到的是,我不知道把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`)
Run Code Online (Sandbox Code Playgroud)

所以Schema::tableblock需要down()lu_benefits_categoriesmigration的函数中和之前的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');
}
Run Code Online (Sandbox Code Playgroud)

之后,php artisan migrate:refreshorphp artisan migrate:reset将起作用。