Laravel 迁移(错误号:150 "Foreign key constraint is incorrectly formed")

Laravel migration (errno: 150 "Foreign key constraint is incorrectly formed")

我有一个订单 table 和一个 sell_shipping_labelsorders.id 引用为外国人。但是,当我 运行 Laravel 迁移时,我得到了可怕的错误代码:

[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1005 Can't create table cheapbooks_test.#sql-b5b_b2a (errno: 150 "Foreign key constraint is incorrectly formed") (SQL: alter table sell_shipping_labels add constraint sell_shipping_labels_order_id_foreign foreign key (order_id) references orders (id))

[Doctrine\DBAL\Driver\PDOException]
SQLSTATE[HY000]: General error: 1005 Can't create table cheapbooks_test.#sql-b5b_b2a (errno: 150 "Foreign key constraint is incorrectly formed")

这是我的 orders table 架构:

   Schema::create('orders', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('user_id');
        $table->integer('book_id');
        $table->integer('status_id');
        $table->double('payment_amount')->nullable();
        $table->timestamp('received_at')->nullable();
        $table->timestamp('paid_at')->nullable();
        $table->timestamps();
        $table->softDeletes();
    });

这是我的 sell_shipping_labels 架构:

Schema::create('sell_shipping_labels', function (Blueprint $table) {
        $table->increments('id');
        $table->unsignedInteger('order_id');
        $table->string('shippo_object_id');
        $table->string('label_url');
        $table->string('tracking_url');
        $table->string('tracking_number');
        $table->timestamp('arrived_at');
        $table->timestamps();
        $table->softDeletes();

        $table->foreign('order_id')->references('id')->on('orders');
    });
}

现在我翻遍了互联网,试图找出问题所在。所有关于这个问题的 post 都是指订单 table 必须创建 BEFORE 具有外键的 table但这对我来说不是问题,因为我的文件顺序正确。

由于increments()创建了一个无符号整数列,您需要将外键列也定义为无符号整数。

Laravel 6+ 中的默认迁移使用 bigIncrements(),因此您需要使用 unsignedBigInteger() 方法:

$table->unsignedBigInteger('order_id');

https://laravel.com/docs/6.x/migrations#foreign-key-constraints

对于旧版本 Laravel 中的默认迁移,使用 unsignedInteger() 方法:

$table->unsignedInteger('order_id');

或:

$table->integer('order_id')->unsigned();

https://laravel.com/docs/5.5/migrations#foreign-key-constraints

对于那些标记答案无效的人:

检查 table 的引擎。就我而言,我在 InnoDB 源 table 中引用了 MyISAM table。将参考 table 引擎更改为 InnoDB 后,它成功了!

  1. 迁移文件的创建方式应首先是父迁移,然后是带有外键的迁移文件。
  2. 另一个 table 中的外键和主 ID 应该完全相似 属性。如果主 ID 是递增的,则使外键为 integer('xxx_id')->unsigned();

我也遇到了同样的错误。我在 users table 中所做的是,

$table->unsignedInteger('role_id')->default(2); table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');

但是我在创建用户 table 之后创建了角色 table。因此,我在用户 table 文件名日期之前编辑了角色迁移文件名日期。像这样,

2013_01_22_091213_create_roles_table.php
2014_10_12_000000_create_users_table.php

终于成功了。也许有时你会遇到这个问题。所以,我发布了它。

检查迁移顺序。如果您的迁移命令试图在命令 table 之前创建 sell_shipping_labels table,这将与 MySQL 一起发生。它似乎继续创建迁移日期,从最旧到最新。换句话说,它试图引用的 table 上的 order_id 应该存在。

我遇到了同样的问题,我更改了创建迁移日期。

我遇到了同样的问题并解决了将数据库类型设置为 innoDB

的问题

在迁移之前创建的 tables 默认情况下来自遗留系统的 MyISAM 和迁移的是 innoDB,所以 table 类型的混合是我的问题案例.

Laravel 5.8.3自带 $table->bigIncrements('id');

改为

$table->increments('id');
$table->integer('order_id')->unsigned();

外键必须是 "unsignedBigInteger" 并且会被修复, 像这样:

$table->unsignedBigInteger('user_id');

$table->foreign('user_id')->references('id')->on('users');

我今天遇到了这个问题。我检查了所有建议的解决方案,例如引用键和外键相同的数据类型、数据库引擎中的相同排序规则和 laravel 配置(database.php)、迁移的日期顺序和其他可能的错误,但任何人都是我的解决方案! 我发现的最后一件事是放在迁移中的 onUpdate 和 onDelete 约束。通过删除它们,我的问题解决了!

致所有使用 laravel 5 查看此内容的人。8.x 我通过改变来解决这个问题 这个

$table->unsignedInteger('foreign_id');

至此

$table->unsignedBigInteger('foreign_id');

这是由于使用了 bigIncrements。 您可以改为删除机会 bigIncrements 以增加关系两侧的增量

我今天遇到了同样的问题。我的 laravel 版本是 5.8.29。我通过以下方式解决了问题:

$table->bigIncrements('id'); //current table primary key and id
$table->unsignedBigInteger('user_id'); // foreigh key
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

希望这有效。

主键和外键应该是相同的数据类型.

如果主键使用无符号big_integer,外键也应该使用无符号big_integer

如果 laravel 5.8 在生成新迁移时默认使用 bigIncrements(请参阅此 pull request),您应该确保您的 foreign key 也是未签名的 big_integer 否则你会得到错误。

Table users:

Schema::create('users', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->string('name');

    ...

}

Table orders:

Schema::create('orders', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->unsignedBigInteger('user_id');

    ...

    $table->foreign('user_id')->references('id')->on('users');
}

希望对您有所帮助。

如果问题还没有解决,请尝试一下。 您需要创建最后一个关联的 table.

您应该先创建订单,然后再创建 sell_shipping_labels table

要解决此问题,您应该将类​​别和用户的迁移文件重命名为餐前迁移文件的日期 table。

[![enter image description here][1]][1]
public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();


        });
    }

I changed $table->bigIncrements('id') to $table->Increments('id')
For this user_id of files table become same integer type as user table field id. After this command worked.

   public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }



For the second table
 {
        Schema::create('files', function (Blueprint $table) {
            $table->increments('id');

});

            Schema::table('files', function($table) {
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
           });
    }

大多数情况下,此错误的原因通常是迁移文件的列出顺序或类型转换导致的错误。

始终确保要对其施加外部约束的文件的迁移发生在父迁移之后。 对于后者,请确保它是一个 unsignedBigInteger ,尽管 laravel (<5.4) 的旧版本可以忽略此类型转换错误。

我今天遇到了这个问题。我的 parent table 主键数据类型和 child table 数据类型相同,但错误仍然存​​在。我发现我的 parent 和 child table 存储引擎不同。我通过从我的 phpmyadmin 制作两个 tables 存储引擎 InnoDB 来解决这个问题。

对于 laravel 6+ 用户,我同意前 2 个答案,它完全取决于 laravel 版本,对于最新版本用户 id 列使用 big integer。因此,从当前迁移中引用用户 id,您需要使用 unsignedBigInteger 作为引用键。 下面是 laravel 6.5.* 的迁移示例,每当我们分配 foreign key 时,请记住您的 当前 laravel版本

Schema::create('galleries', function (Blueprint $table) {
        $table->bigIncrements('id');
        ==>$table->unsignedBigInteger('user_id');
        $table->string('title');
        $table->string('description');
        $table->timestamps();
        ==>$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
    });

在 Laravel 中添加外键的更好方法是使用别名。所以代替:

$table->unsignedBigInteger('user_id'); // foreigh key
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

我们可以简单地这样做:

$table->foreignId('user_id')->constrained();

这对我有用。谢谢!

我用的时候问题解决了 bigInteger('user_id')->无符号();

用简单的代码避免所有这两行代码 这意味着 sell_shipping_labels.order_id 引用 orders table 上的 id,如下所示

Schema::table('sell_shipping_labels', function (Blueprint $table) {
    $table->foreignId('order_id')->constrained('orders');
});

如果您的迁移依赖于父迁移,那么您需要确保先运行父迁移。所以我所做的是:

  1. 复制当前子迁移的内容
  2. 使用 php artisan make:migration create_<models>_table
  3. 重新创建迁移文件
  4. 运行 php artisan migrate:fresh

希望有用。