【问题标题】:Laravel migration (errno: 150 "Foreign key constraint is incorrectly formed")Laravel 迁移 (errno: 150 "外键约束格式不正确")
【发布时间】:2018-05-23 13:24:04
【问题描述】:

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

[照亮\数据库\查询异常]
SQLSTATE[HY000]: 一般错误: 1005 Can't create table cheapbooks_test.#sql-b5b_b2a (errno: 150 "外键约束格式不正确") (SQL: alter table sell_shipping_labels add constraint sell_shipping_labels_order_id_foreign foreign 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');
    });
}

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

【问题讨论】:

  • Laravel 7+ 允许你使用 $table->foreignId('order_id')->constrained(); 而不是 $table->foreign('order_id')->references('id')->on('orders');
  • @afaolek 建议对我有用。虽然没有尝试过其他答案(无论如何都不需要)

标签: mysql laravel laravel-5 laravel-artisan artisan-migrate


【解决方案1】:

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

【讨论】:

  • 我已经更新了我的表架构,但我仍然得到相同的错误代码。
  • @FrenchMajesty 您是否尝试重新创建数据库?如果你这样做了,请发布新的错误消息,因为我很确定语法是正确的。
  • 删除并重新创建我的数据库以及您的答案就可以了。谢谢!
  • 我必须在最新版本上使用 unsignedBigInteger(如下面的答案)。
  • $table->unsignedBigInteger('order_id');这对我有用。谢谢
【解决方案2】:

外键必须是“unsignedBigInteger”,它会被修复, 像这样:

$table->unsignedBigInteger('user_id');

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

【讨论】:

  • 非常感谢。这种方法对我有用。但我不明白为什么其他方法对我不起作用。任何见解都会很好。
【解决方案3】:

主键和外键应属于同一数据类型

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

如果 laravel 5.8 在生成新迁移时默认使用bigIncrements(请参阅此pull request),您应该确保您的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');
}

希望这会有所帮助。

【讨论】:

  • 非常感谢。这种方法对我有用。但我不明白为什么其他方法对我不起作用。任何见解都会很好。
  • 最佳答案在这里。谢谢!
【解决方案4】:

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

$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

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

【讨论】:

    【解决方案5】:

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

    改成

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

    【讨论】:

    • 这对我有用。谢谢。另外,我们可以将 order_id 设为 bigInteger。
    • 为什么会出现这个问题?当它是大增量时我们如何解决它?
    • 这对我有用,谢谢。我尝试以上任何一个答案都不起作用,但你的答案神奇地起作用了谢谢。
    【解决方案6】:

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

    始终确保要对其施加外部约束的文件的迁移在父迁移之后进行。 对于后者,请确保它是一个 unsignedBigInteger ,尽管以前版本的 laravel (

    【讨论】:

      【解决方案7】:
      1. 迁移文件的创建方式应该是父迁移首先出现,然后是具有外键的迁移文件。
      2. 另一个表中的外键和主ID应该具有完全相同的属性。如果主 id 是递增的,则使外键 integer('xxx_id')->unsigned();

      【讨论】:

      • 谢谢,这就是问题所在!
      【解决方案8】:

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

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

      【讨论】:

      • 如果你仔细阅读我写的帖子,很多人提到了迁移的顺序,这是我检查过的很好,所以这不是问题。
      【解决方案9】:

      致所有使用 laravel 5.8.x 的人 我通过改变来解决这个问题 这个

      $table->unsignedInteger('foreign_id');
      

      到这里

      $table->unsignedBigInteger('foreign_id');
      

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

      【讨论】:

      • 完美又漂亮!
      【解决方案10】:

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

      检查表的引擎。在我的例子中,我在 InnoDB 源表中引用了一个 MyISAM 表。将引用表引擎改成 InnoDB 后,就成功了!

      【讨论】:

        【解决方案11】:

        用简单的方式避免所有这两行代码 这意味着sell_shipping_labels.order_id 引用了orders 表上的ID,如下所示

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

        【讨论】:

          【解决方案12】:

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

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

          【讨论】:

            【解决方案13】:

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

            希望这行得通。

            【讨论】:

              【解决方案14】:

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

              【讨论】:

                【解决方案15】:

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

                【讨论】:

                  【解决方案16】:

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

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

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

                  【讨论】:

                    【解决方案17】:
                    [![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');
                               });
                        }
                    

                    【讨论】:

                      【解决方案18】:

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

                      【讨论】:

                      • 请详细说明您是如何解决问题的,以及您是如何解决问题的。
                      • 我的数据库类型默认是innoDB但是不起作用?你是怎么解释更多的?
                      【解决方案19】:

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

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

                      我们可以这样做:

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

                      这对我有用。谢谢!

                      【讨论】:

                        【解决方案20】:

                        我的问题在我使用时解决了 bigInteger('user_id')->unsigned();

                        【讨论】:

                          【解决方案21】:

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

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

                          希望有效。

                          【讨论】:

                            猜你喜欢
                            • 2015-12-16
                            • 2019-09-10
                            • 1970-01-01
                            • 2017-04-13
                            • 2019-09-17
                            • 2020-12-16
                            • 1970-01-01
                            • 2019-07-27
                            相关资源
                            最近更新 更多