laravel errno 150 外键约束格式不正确

Posted

技术标签:

【中文标题】laravel errno 150 外键约束格式不正确【英文标题】:laravel errno 150 foreign key constraint is incorrectly formed 【发布时间】: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('公司'); 【参考方案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 key 和 laravel migrations

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

【讨论】:

感谢您的详尽解释。第 3 点的第一个要点对我有用! Unique : the referenced column must be unique - 这在 mysql 中不一定是正确的(请记住,错误消息与 laravel 无关,它来自 MySQL)。此要求曾经适用于 NDB 表类型,v8.0 将 NDB 要求与 innodb 对齐。对于广泛使用的 innodb 表类型,要求是引用的列必须被索引。 如果您想要更全面的可能原因列表,请查看以下 SO 问题:***.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 顺利运行

【讨论】:

以上是关于laravel errno 150 外键约束格式不正确的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 抛出 errno:150 “外键约束的格式不正确”,尽管语法正确

laravel 8 (errno: 150 "外键约束格式不正确")

MySQL创建表:错误1005 errno:150“外键约束形成错误”

一般错误:1005 无法创建表 errno:150“外键约束格式不正确”)

MySQL + Rails:errno:150“外键约束格式不正确”

Laravel - 外键约束的格式不正确