27

我有一个订单表和一个作为外来sell_shipping_labels引用的。orders.id但是,当我运行 Laravel 迁移时,我得到了可怕的错误代码:

[Illuminate\Database\QueryException]
SQLSTATE[HY000]:一般错误:1005 无法创建表cheapbooks_test#sql-b5b_b2a(errno: 150 "Foreign key constraint is wrongly forms") (SQL: alter table sell_shipping_labelsadd constraint sell_shipping_labels_order_id_foreignforeign key ( order_id) 引用orders( id))

[Doctrine\DBAL\Driver\PDOException]
SQLSTATE[HY000]:一般错误:1005 无法创建表cheapbooks_test#sql-b5b_b2a(errno: 150 "外键约束格式不正确")

这是我的orders表架构:

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

现在我把互联网颠倒过来试图找出问题所在。所有关于这个问题的帖子都提到必须在具有外键的表之前创建订单表,但这对我来说不是问题,因为我的文件顺序正确。

4

21 回答 21

61

由于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

于 2017-12-09T13:11:27.177 回答
22

外键必须是“unsignedBigInteger”,并且会被修复,如下所示:

$table->unsignedBigInteger('user_id');

$table->foreign('user_id')->references('id')->on('users');
于 2019-04-21T14:17:27.510 回答
18

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

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

如果 laravel 5.8bigIncrements在生成新迁移时默认使用(请参阅此拉取请求),您应该确保您foreign key的也是未签名 的big_integer,否则您将收到错误消息。

users

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

    ...

}

orders

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

    ...

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

希望这可以帮助。

于 2019-07-27T13:29:56.767 回答
8

我也遇到了同样的错误。我在用户表中所做的是,

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

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

2013_01_22_091213_create_roles_table.php
2014_10_12_000000_create_users_table.php

最后它起作用了。也许有时你会遇到这个问题。所以,我发布了它。

于 2019-01-22T10:48:47.660 回答
7

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

将其更改为

$table->increments('id');
$table->integer('order_id')->unsigned();
于 2019-03-09T16:10:19.837 回答
4

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

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

于 2019-10-16T16:12:09.473 回答
3
  1. 迁移文件的创建方式应该是父迁移首先出现,然后是具有外键的迁移文件。
  2. 另一个表中的外键和主 ID 应该具有完全相同的属性。如果主 id 是递增的,则使外键 integer('xxx_id')->unsigned();
于 2018-11-05T09:18:06.583 回答
2

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

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

于 2019-01-24T14:03:45.480 回答
2

对于那些标记答案不起作用的人:

检查表的引擎。就我而言,我在InnoDB源表中引用了MyISAM表。将引用表引擎更改为 InnoDB 后,它工作了!

于 2018-09-23T09:37:56.030 回答
2

对于任何使用 laravel 5.8.x 看这个的人,我通过改变这个来解决这个问题

$table->unsignedInteger('foreign_id');

对此

$table->unsignedBigInteger('foreign_id');

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

于 2019-07-01T13:15:42.693 回答
2

避免使用简单的所有这两行代码,这意味着表sell_shipping_labels.order_id上的引用 idorders如下

Schema::table('sell_shipping_labels', function (Blueprint $table) {
    $table->foreignId('order_id')->constrained('orders');
});
于 2021-05-24T10:02:28.037 回答
1

对于 laravel 6+ 用户,我同意前 2 个答案,这完全取决于 laravel 版本,对于最新版本的用户id列使用big integer。因此,id从当前迁移中引用用户,您需要将unsignedBigInteger其用作参考键。Bellow 是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');
    });
于 2019-11-24T05:08:15.277 回答
1

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

默认情况下,在迁移之前创建的表是来自遗留系统的“MyISAM”和已迁移innoDB的表,因此在我的情况下,表类型的混合是一个问题。

于 2019-02-07T21:59:23.123 回答
1

我今天遇到了同样的问题。我的 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');

希望这有效。

于 2019-07-26T17:36:17.043 回答
0
[![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');
           });
    }

在此处输入图像描述

于 2019-08-31T06:07:16.853 回答
0

如果问题仍未解决,请尝试。您需要创建最后一个关联表。

您应该首先创建订单,然后创建 sell_shipping_labels 表

要解决此问题,您应该将 Category 和 Users 的迁移文件重命名为 before Meals 迁移文件的日期,该文件创建这些 before Meals 表。

于 2019-07-30T04:41:51.140 回答
0

当我使用 bigInteger('user_id')->unsigned(); 时,我的问题得到了解决

于 2021-01-14T07:50:49.950 回答
0

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

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

我们可以简单地这样做:

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

这对我有用。谢谢!

于 2020-08-17T13:35:10.123 回答
0

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

于 2019-06-30T14:02:53.043 回答
0

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

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

希望有效。

于 2021-08-21T22:33:44.240 回答
0

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

于 2019-10-23T10:37:43.617 回答