【问题标题】:laravel errno 150 foreign key constraint is incorrectly formedlaravel errno 150 外键约束格式不正确
【发布时间】:2017-04-13 07:25:45
【问题描述】:

谁能帮我解决这个问题?

有 3 个表有 2 个外键:

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

Schema::create('firms', function (Blueprint $table) {
    $table->increments('id');
    $table->string('title')->nullable();
    $table->integer('user_id')->unsigned()->nullable();
    $table->foreign('user_id')->references('id')->on('users');
    $table->timestamps();
});

Schema::create('jobs', function (Blueprint $table) {
    $table->increments('id');
    $table->string('title')->nullable();
    $table->integer('firm_id')->unsigned()->nullable();
    $table->foreign('firm_id')->references('id')->on('firms');
    $table->timestamps();
});
                    

运行迁移后出错:

[Illuminate\Database\QueryException]
  SQLSTATE[HY000]: General error: 1005 Can't create table `job`.`#sql-5fc_a1`
   (errno: 150 "Foreign key constraint is incorrectly formed") (SQL: alter ta
  ble `firms` add constraint `firms_user_id_foreign` foreign key (`user_id`)
  references `users` (`id`))

  [PDOException]
  SQLSTATE[HY000]: General error: 1005 Can't create table `job`.`#sql-5fc_a1`
   (errno: 150 "Foreign key constraint is incorrectly formed")

【问题讨论】:

  • 抱歉,它不起作用:Schema::create('firms', function (Blueprint $table) { $table->increments('id')->unsigned(); Schema::create ('jobs', function (Blueprint $table) { $table->increments('id'); $table->integer('firm_id')->unsigned(); $table->foreign('firm_id')- >references('id')->on('firms');
  • 这也不起作用:Schema::create('firms', function (Blueprint $table) { $table->increments('id'); Schema::create('jobs' , function (Blueprint $table) { $table->increments('id'); $table->integer('firm_id'); $table->foreign('firm_id')->references('id')-> on('公司');

标签: php mysql laravel-5


【解决方案1】:

在外键的情况下,被引用的和被引用的字段必须具有完全相同的数据类型。

您在usersfirms 中将id 字段创建为有符号 整数。但是,您将两个外键都创建为 无符号 整数,因此键的创建失败。

您需要将unsigned 子句添加到id 字段定义中,或者从外键字段中删除unsigned 子句。

【讨论】:

  • 很好,对我有帮助。
  • 忘记说这很重要的所有其他事情the referenced and referencing fields must have exactly the same data type.我几乎要上吊了。谢谢老兄。
  • 我遇到了这个错误,我使用了正确的unsignedBigInteger 作为外键,但是这个错误再次出现。我们必须确定enableForeignKeyConstraints。我用这个Schema::enableForeignKeyConstraints();
【解决方案2】:
  • 用户
  • 收银员转介用户
  • 学生指收银员

此外,在 laravel 中声明外键时,您所引用的所有表都必须位于顶部。在这种情况下,您可以使用“->unsigned()”修饰符..

【讨论】:

  • 你能解释一下这是如何回答这个问题的吗?
  • 如您所见,“用户”表位于顶部,收银员有“外键”,指的是与学生相同的“用户”表。创建迁移时只需保持表格井井有条。
【解决方案3】:

大多数情况下,由于两个表的数据类型不匹配,会发生这种错误。

主键表和外键表都应该使用相同的数据类型和相同的选项。

例如:

用户

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

订单

 Schema::create('orders', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->bigInteger('product_id')->unsigned();
            $table->foreign('product_id')->references('id')->on('products');
            $table->bigInteger('user_id')->unsigned();
           $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

            $table->timestamp('added_on');
        });

在上面的例子中,我试图从订单表中为用户表分配外键,但我在订单表中有 bigInteger 数据表,而在用户表中,我有简单的整数。这就是它产生这种错误的原因。

另外,如果你使用了 unsigned()nullable() 等带有主键或外键的选项,那么你应该在两个地方都使用相同的选项。

【讨论】:

    【解决方案4】:

    我们是餐桌上的人:

    Schema::create('villes', function (Blueprint $table) {
                $table->bigIncrements('idVille'); // bigIncrement(8 bits)
                $table->string('nomVille');
                $table->timestamps();
            });
    

    例如用户表中的外键:

    Schema::table('users', function (Blueprint $table) {
                $table->bigInteger('ville_idVille')->unsigned()->after('tele');
                $table->foreign('ville_idVille')->references('idVille')->on('villes');
            });
    

    【讨论】:

      【解决方案5】:

      如果您设置引用字段并且具有完全相同的数据类型但存在错误 您可以更改日期迁移文件 只是它的工作

      【讨论】:

        【解决方案6】:

        这个答案并不比之前的六个答案好,但它是关于导致laravel-errno-150-foreign-key-constraint-is-incorrectly-formed 的原因以及如何专门针对 laravel 修复的更全面的答案。

        1) 拼写:有时,引用的column name 或引用的table name 的拼写错误可能会引发此错误,您不会知道,因为错误跟踪不是很有描述性.

        2) 唯一:引用的列必须是唯一的,或者通过在迁移中的列定义中添加 ->primary() 或添加 ->unique() 或添加 ->index() 来建立索引。

        3) 数据类型:被引用的和被引用的字段必须具有完全相同的数据类型。这一点怎么强调都不过分。

        • 对于bigincrements,预期数据类型为bigInteger('column_name')->unsigned();

        • increments 预期为 integer('column_name')->unsigned(); 等。

        4) Remnants : 当这个错误发生时并不意味着表没有被迁移,而是被迁移了但是没有设置外键列并且没有添加到migration table因此运行php artisan migrate:reset 将删除除故障表之外的其他表,因此建议手动删除故障表以避免进一步的错误。

        5) Order :这通常是导致此错误的最常见原因,必须在 reference table 之前创建或迁移表 referenced 否则工匠将找不到集成外键的位置.确保迁移过程的顺序重命名迁移文件示例:

        • 表A:2014_10_12_000000_create_users_table.php
        • 表B:2014_10_12_100000_create_password_resets_table.php

        这表明表 A 将始终在表 B 之前进行更改,我将表 B 重命名为 2014_10_11_100000_create_password_resets_table.php 现在它将在表 A 之前迁移。

        6) 启用外键:如果所有其他方法都失败,则在您的迁移代码示例之前的function up() 中添加Schema::enableForeignKeyConstraints();

        class CreateUsersTable extends Migration
        {
         /**
          * Run the migrations.
          *
          * @return void
          */
         public function up()
         {
            Schema::enableForeignKeyConstraints();
            Schema::create('users', function (Blueprint $table) {
                $table->increments('id');
                $table->string('name');
                $table->string('email')->unique();
                $table->string('password');
                $table->rememberToken();
                $table->timestamps();
            });
         }
        
         /**
          * Reverse the migrations.
          *
          * @return void
          */
         public function down()
         {
            Schema::dropIfExists('users');
         }
        }
        

        要了解更多信息,请参阅 laravel foreign keylaravel migrations

        提及我在 cmets 中错过的任何修复,谢谢。

        【讨论】:

        • 感谢您的详尽解释。第 3 点的第一个要点对我有用!
        • Unique : the referenced column must be unique - 这在 MySQL 中不一定是正确的(请记住,错误消息与 laravel 无关,它来自 MySQL)。此要求曾经适用于 NDB 表类型,v8.0 将 NDB 要求与 innodb 对齐。对于广泛使用的 innodb 表类型,要求是引用的列必须被索引。
        • 如果您想要更全面的可能原因列表,请查看以下 SO 问题:stackoverflow.com/questions/1457305/…
        • 非常感谢。 #3 像魅力一样工作
        • 订单是我的错误。谢谢。
        【解决方案7】:

        对于 PHP laravel 5.8,使用这种格式的无符号修饰符

        $table->unsignedBigInteger('user_id');
        

        删除数据库中的所有表并再次运行迁移

        【讨论】:

        • 注意:在外键中引用的迁移表似乎必须已经创建。否则,我会得到“errno 150 外键约束格式不正确”。
        【解决方案8】:

        如果参考表主键在 BigIcrements 中,则使用 BigInteger 作为外键,如下所示

        表 ATable

        public function up()
        {
            Schema::create('a_tables', function (Blueprint $table) {
                $table->bigIncrements('id');
           }
        }
        

        表 BTable

        public function up()
        {
            Schema::create('b_tales', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->bigInteger('a_tables_id')->unsigned();
             $table->foreign('a_tables_id')->references('id')->on('a_tables')->onDelete('cascade');
           }
        }
        

        【讨论】:

          【解决方案9】:
          public function up() {     Schema::create('companies', function (Blueprint $table) {         $table->bigIncrements('id');         $table->string('name');         $table->text('address');         $table->string('tel1');         $table->string('tel2');         $table->integer('owner');         $table->unsignedBigInteger('access_id');         $table->string('depot_number')->default(2);         $table->timestamps();           $table->foreign('access_id')->references('id')->on('accesses')             ->onDelete('cascade');     }); } 
          
          public function up() {     Schema::create('accesses', function (Blueprint $table) {         $table->bigIncrements('id');         $table->string('type');         $table->string('description');         $table->timestamps();     }); } 
          

          在您的 database/migrations 文件夹中,按名称排序。然后确保 create_accesses_tablecreate_companies_table 之前:

          【讨论】:

            【解决方案10】:

            我尝试了此线程中提供的所有答案。

            没有任何效果。

            然后我发现我忘了删除 phpMyadmin 中的“迁移”表。

            我从 phpMyAdmin 中删除了所有表,但迁移表除外。这就是为什么错误一次又一次地持续存在的原因。

            【讨论】:

              【解决方案11】:

              这个答案与 Laravel 7.x 有关。所以报错:

              errno: 150 "外键约束格式不正确"

              在迁移迁移时可能由于多种原因而发生。我熟悉的一个常见原因是迁移顺序。

              假设我们有两个表“users”和“roles”,并且“users”表有一个外键引用“roles”表上的“id”列。所以请确保“角色”在“用户”表之前迁移。

              所以迁移的顺序很重要。这很明显,因为 MySQL 引用未知表的“id”列是没有意义的。

              第二个原因是错误的数据类型。在 laravel 7.x 中,我们使用“id()”方法作为主键。所以请确保预期的外键(在我的情况下是“users”表中的“role_id”)是“bigInteger”并且是“unsigned”。

              这是我的代码:

              Schema::create('roles', function (Blueprint $table) {
                      $table->id();
                      $table->string('name');
                      $table->string('slug')->nullable();
                      $table->timestamps();
                  });
              
              
              Schema::create('users', function (Blueprint $table) {
                      $table->id();
                      $table->bigInteger("role_id")->unsigned();
                      $table->string('name');
                      $table->string('email')->unique();
                      $table->timestamp('email_verified_at')->nullable();
                      $table->string('password');
                      $table->rememberToken();
                      $table->timestamps();
              
                      $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
                  });
              
              public function down()
              {
                  Schema::table('users', function(Blueprint $table)
                  {
                      $table->dropForeign('users_role_id_foreign'); 
                  });
                  Schema::dropIfExists('users');
              }
              

              所以在上面的代码中,我必须先迁移“角色”表,然后迁移“用户”表。所以 MySQL 可以为角色表创建外键。

              我将子迁移(具有外键的迁移)移动到临时文件夹。并在迁移父迁移后恢复它(在我的情况下是“角色”表,然后迁移子迁移(“用户”迁移)。

              作为小贴士:在删除依赖迁移(包含外键的迁移)时,首先删除外键。 Laravel 在删除外键“__foreign”时使用特定的命名约定。

              编码愉快,准备好迎接 PHP 8 的开创性发布。

              【讨论】:

              • 感谢您,真正让它点击的地方是意识到在调用伪造密钥表时需要之前迁移它。呃! ty
              【解决方案12】:

              这里的主要概念是您必须确保主键和外键类型相同。例如,让您的第一个表迁移

              public function up()
              {
                  Schema::create('chapters', function (Blueprint $table) {
                      $table->id();
                      $table->string('title');
                      $table->timestamps();
                  });
              }
              

              那么你的第二个表迁移将是

              public function up()
              {
                  Schema::create('classifications', function (Blueprint $table) {
                      $table->id();
                      $table->string('title');
                      $table->unsignedBigInteger('chapter_id');
                      $table->timestamps();
                      $table->foreign('chapter_id')->references('id')->on('chapters')->onDelete('cascade');
                  });
              }
              

              这里“chapter”表中的“id”和“classifications”表中的“chapter_id”相同,即“unsignedBigInteger”。

              再次,如果您遇到错误,则将“章节”表中的“$table->id();”更改为“$table->bigIncrements('id');”。

              希望对你有帮助

              【讨论】:

                【解决方案13】:

                对于 laravel 7 的迁移错误为

                ("SQLSTATE[HY000]: 一般错误: 1005 无法创建表laraveltesting.reviews (errno: 150 "外键约束格式不正确")")

                迁移顺序是最重要的,因此应先迁移父表,然后再迁移子表 图一:migration order while getting error

                
                        Schema::create('products', function (Blueprint $table) {
                            $table->id();
                            $table->string('name');
                            $table->text('detail');
                            $table->float('price');
                            $table->integer('stock');
                            $table->float('discount');
                            $table->timestamps();
                        });
                
                 Schema::create('reviews', function (Blueprint $table) {
                            $table->id();
                            $table->foreignId('product_id')->constrained('products')->cascadeOnDelete();
                            $table->string('customer');
                            $table->text('review');
                            $table->integer('star');
                
                            $table->timestamps();
                        });
                

                这会导致迁移时出现错误,这可以通过更改迁移顺序来解决,方法是从图像 1 重命名迁移,如图 2 所示。应该首先迁移书籍表,然后只迁移评论表

                图片2:Order of migration for the successful migration

                【讨论】:

                  【解决方案14】:

                  如果你得到错误改变 $table->id()(references) by $table->increments('id')

                  【讨论】:

                    【解决方案15】:

                    经过所有努力与我合作

                    从数据库和(迁移表)

                    删除(用户表)
                    然后“取消注释”您的外键关系
                    示例: $table->string('pass1'); $table->foreign('pass1')->references('email')->on('abs');
                    然后运行: php artisan migrate 顺利运行

                    【讨论】:

                      猜你喜欢
                      • 2019-09-17
                      • 2020-12-16
                      • 1970-01-01
                      • 2021-12-30
                      • 2017-05-29
                      • 1970-01-01
                      • 2018-06-19
                      • 2018-03-02
                      相关资源
                      最近更新 更多