Laravel Migration外键约束不正确

问题描述 投票:22回答:15

迁移我的数据库时出现此错误,下面是我的代码,后面是我在尝试运行迁移时遇到的错误。

 public function up()
    {
        Schema::create('meals', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id')->unsigned();
            $table->integer('category_id')->unsigned();
            $table->string('title');
            $table->string('body');
            $table->string('meal_av');
            $table->timestamps();

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

            $table->foreign('category_id')
                ->references('id')
                ->on('categories')
                ->onDelete('cascade');
        });
    }  

错误信息

[Illuminate\Database\QueryException]                                         
      SQLSTATE[HY000]: General error: 1005 Can't create table `meal`.`#sql-11d2_1  
      4` (errno: 150 "Foreign key constraint is incorrectly formed") (SQL: alter   
      table `meals` add constraint meals_category_id_foreign foreign key (`catego  
      ry_id`) references `categories` (`id`) on delete cascade) 
mariadb laravel-5.1
15个回答
28
投票

在Laravel中创建新表时。将生成迁移,如:

$table->bigIncrements('id');

而不是(在较旧的Laravel版本中):

$table->increments('id');

使用bigIncrements时,外键需要bigInteger而不是整数。所以你的代码看起来像这样:

public function up()
    {
        Schema::create('meals', function (Blueprint $table) {
            $table->increments('id');
            $table->unsignedBigInteger('user_id'); //changed this line
            $table->unsignedBigInteger('category_id'); //changed this line
            $table->string('title');
            $table->string('body');
            $table->string('meal_av');
            $table->timestamps();

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

            $table->foreign('category_id')
                ->references('id')
                ->on('categories')
                ->onDelete('cascade');
        });
    }  

你也可以使用increments代替bigIncrements,如Kiko Sejio所说。

Integer和BigInteger之间的区别在于大小:

  • int => 32位
  • bigint => 64位

2
投票

也许这对任何登陆这里的人都有帮助:我刚刚经历过同样的问题,而在我的情况下,我在外键约束之前的外键列上设置了一个(复合)唯一约束。我通过在“外国”声明之后放置“独特”声明来解决问题。

作品:

$table->foreign('step_id')->references('id')->on('steps')->onDelete('cascade');
$table->unique(['step_id','lang']);

不起作用:

$table->unique(['step_id','lang']);
$table->foreign('step_id')->references('id')->on('steps')->onDelete('cascade');

2
投票

我得到了数据类型未匹配问题的相同消息。

我使用bigIncrements()作为'id',当我用它作为外键(使用bigInteger())时,我得到了错误。

我找到了解决方案,bigIncrements()返回unsignedBigInteger。因此需要在外键中使用unsignedBigInteger()而不是bigInteger()

分享这个因为它可能会帮助别人


0
投票

在您的字段上添加 - > nullable()并确保您引用的所有字段确实存在。


0
投票

应该对迁移文件的创建顺序进行排序,并且外键应该具有与另一个表中的主键完全相似的属性。


0
投票

请记住,引用和引用字段必须具有完全相同的数据类型。


-1
投票

您应该在创建“餐”时首先创建类别和用户表

要解决此问题,您应该将类​​别和用户的迁移文件重命名为在Meals表之前创建那些的Meals Migration文件之前的日期。


sample:
2019_04_10_050958_create_users_table 
2019_04_10_051958_create_categories_table
2019_04_10_052958_create_meals_table

17
投票

@JuanBonnett你的问题激发了我的答案,我在laravel上采用自动化过程而不考虑文件本身的创建时间。根据工作流程,餐桌将在表(类别)之前创建,因为我创建了模式文件(餐)在类别之前。那是我的错。


11
投票

只需在外键的末尾添加->unsigned()->index()即可


10
投票

对我来说,一切都是正确的顺序,但它仍然无法正常工作。然后我通过摆弄来发现主键必须是无符号的。

//this didn't work
$table->integer('id')->unique();
$table->primary('id');

//this worked
$table->integer('id')->unsigned()->unique();
$table->primary('id');

//this worked 
$table->increments('id');

5
投票

就我而言,新的laravel约定导致了这个错误。

只需通过表格创建id的简单交换就可以了。

$table->increments('id'); // ok

, 代替:

$table->bigIncrements('id'); // was the error.

已经与Laravel v5.8合作,之前从未遇到此错误。


4
投票

必须自上而下创建迁移。

首先为不属于任何人的表创建迁移。

然后为属于上一个的表创建迁移。


简化了表引擎问题的答案:

要为表设置存储引擎,请在架构构建器上设置engine属性:

Schema::create('users', function ($table) {
    $table->engine = 'InnoDB';

    $table->increments('id');
});

来自Laravel Docs:https://laravel.com/docs/5.2/migrations


4
投票

如果您在外键定义中使用->onDelete('set null'),请确保外键字段本身是nullable()

//Column definition
$table->integer('user_id')->unsigned()->index()->nullable(); //index() is optional

//...
//...

//Foreign key 
$table->foreign('user_id')
      ->references('id')
      ->on('users')
      ->onDelete('set null');

4
投票

你应该创建你的迁移,例如我希望我的users有一个role_id字段来自我的roles

我首先开始让我的角色迁移php artisan make:migration create_roles_table --create=roles

然后我的第二个用户迁移php artisan make:migration create_users_table --create=users

php artisan migration将使用创建的文件2017_08_22_074128_create_roles_table.php和2017_08_22_134306_create_users_table的顺序执行,检查日期时间顺序,即执行顺序。

文件2017_08_22_074128_create_roles_table.php

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

2017_08_22_134306 create_users_table

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('role_id')->unsigned();
        $table->string('name');
        $table->string('phone', 20)->unique();
        $table->string('password');
        $table->rememberToken();
        $table->boolean('active');
        $table->timestamps();
        $table->foreign('role_id')->references('id')->on('roles');
    });
}

2
投票

在我的例子中,问题是其中一个引用的表是InnoDB,另一个是MyISAM。

MyISAM不支持外键关系。

所以,现在这两个表都是InnoDB。问题解决了。

© www.soinside.com 2019 - 2024. All rights reserved.