迁移:无法在laravel中添加外键约束

001*_*221 175 migration foreign-keys laravel eloquent laravel-4

我正在尝试在Laravel中创建外键但是当我使用artisani 迁移我的表时抛出以下错误:

[Illuminate\Database\QueryException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL
: alter table `priorities` add constraint priorities_user_id_foreign foreign 
key (`user_id`) references `users` (`id`))     
Run Code Online (Sandbox Code Playgroud)

我的迁移代码如下:

优先级迁移文件

public function up()
{
    //
    Schema::create('priorities', function($table) {
        $table->increments('id', true);
        $table->integer('user_id');
        $table->foreign('user_id')->references('id')->on('users');
        $table->string('priority_name');
        $table->smallInteger('rank');
        $table->text('class');
        $table->timestamps('timecreated');
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    //
    Schema::drop('priorities');
}
Run Code Online (Sandbox Code Playgroud)

用户迁移文件

public function up()
{
    //
    Schema::table('users', function($table)
    {
    $table->create();
    $table->increments('id');
    $table->string('email');
    $table->string('first_name');
    $table->string('password');
    $table->string('email_code');
    $table->string('time_created');
    $table->string('ip');
    $table->string('confirmed');
    $table->string('user_role');
    $table->string('salt');
    $table->string('last_login');

    $table->timestamps();
    });
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    //
        Schemea::drop('users');
}
Run Code Online (Sandbox Code Playgroud)

关于我做错了什么的想法,我现在想要得到这个,因为我需要创建很多表,例如用户,客户,项目,任务,状态,优先级,类型,团队.理想我想创建与外键,i..e持此数据表clients_projectproject_tasks等.

希望有人能帮助我开始.

提前致谢.

Ant*_*iro 322

分两步添加它,也可以使它无符号:

public function up()
{
    Schema::create('priorities', function($table) {
        $table->increments('id', true);
        $table->integer('user_id')->unsigned();
        $table->string('priority_name');
        $table->smallInteger('rank');
        $table->text('class');
        $table->timestamps('timecreated');
    });

   Schema::table('priorities', function($table) {
       $table->foreign('user_id')->references('id')->on('users');
   });

}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,安东尼奥!对我来说,问题不是在user_id列上添加unsigned(),以便它与users表上的id列的数据类型匹配.Laravel的增量('id')函数创建一个无符号整数,因此外键列也需要是无符号的. (107认同)
  • 如果您的user.id是bigIncrements,请使用$ table-> unsignedBigInteger('user_id') (8认同)
  • 添加unsigned,除了分离到`Schema :: table`方法帮助!谢谢! (6认同)
  • 解决方案在@BradGriffith的评论中.如上所述,我根本不需要分开.也许更好地相应地更新答案. (6认同)
  • 对我而言,它也没有使id无符号.谢谢你的提示. (4认同)
  • 我有同样的错误,谢谢.但除非您认为它看起来更漂亮,否则您不必将它们分开. (4认同)
  • 在v5.6中添加“未签名”非常重要,谢谢@Antonio (2认同)
  • 现在有一个unsignedInteger(),所以只需使用:$ table-> unsignedInteger('user_id');` (2认同)

haa*_*kym 102

问题已经回答了,但希望这可能有助于其他人.

这个错误发生在我身上,因为我在密钥作为其原始表中的主键存在之前首先创建了带有外键的迁移表.迁移按创建顺序执行,如运行后生成的文件名所示migrate:make.例如2014_05_10_165709_create_student_table.php.

解决方案是使用外键将文件重命名为比具有主键的文件更早的时间,如下所示:http://forumsarchive.laravel.io/viewtopic.php?id = 10246

我想我也必须加入 $table->engine = 'InnoDB';

  • **$ table-> engine ='InnoDB';**需要在MySql级别强制执行外键.默认的laravel引擎是MyIsam,它不支持外键! (13认同)
  • 重命名迁移文件并出现以下错误后:无法打开流:无需运行此类文件或目录(并显示旧的迁移名称):composer dump-autoload (4认同)
  • 这对我也有用,谢谢.但是我觉得这样做有点奇怪.我的意思是,它是有道理的,但应该有一种方法来指定迁移执行的顺序,而不是手动重命名文件和在过程中提出假日期 (2认同)
  • 我来到这里并不是因为我收到任何错误,但我能够将错误的值添加到作为外键的列中.然后我看到了关于InnoDB的评论和回答.这很好知道.多谢你们 :) (2认同)
  • 迁移时,创建迁移的顺序仍然很重要.我遇到了这个问题,但这解决了它. (2认同)

小智 47

在我的情况下,问题是主表已经有记录,我强迫新列不是NULL.因此,在新列中添加 - > nullable()就可以了.在问题的例子中会是这样的:

$table->integer('user_id')->unsigned()->nullable();

要么:

$table->unsignedInteger('user_id')->nullable();

希望这有助于某人!


che*_*aby 41

拉拉威尔^ 5.8

从Laravel 5.8开始,迁移存根在默认情况下对ID列使用bigIncrements方法。以前,使用递增方法创建ID列。

这不会影响项目中的任何现有代码。但是,请注意,外键列必须具有相同的类型。因此,使用增量方法创建的列不能引用使用bigIncrements方法创建的列。

资料来源:Migrations&bigIncrements


假设您正在构建一个基于角色的简单应用程序,并且需要在PIVOT“ role_user”中引用user_id

2019_05_05_112458_create_users_table.php

// ...

public function up()
{
    Schema::create('users', function (Blueprint $table) {

        $table->bigIncrements('id');

        $table->string('full_name');
        $table->string('email');
        $table->timestamps();
    });
}
Run Code Online (Sandbox Code Playgroud)

2019_05_05_120634_create_role_user_pivot_table.php

// ...

public function up()
{
    Schema::create('role_user', function (Blueprint $table) {

        // this line throw QueryException "SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint..."
        // $table->integer('user_id')->unsigned()->index();

        $table->bigInteger('user_id')->unsigned()->index(); // this is working
        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
    });
}
Run Code Online (Sandbox Code Playgroud)

如您所见,注释行将引发查询异常,因为如升级说明中所述,外键列必须为同一类型,因此您需要将前键(在此示例中为user_id)更改为BIGINTEGERROLE_USER表或改变bigIncrements方法增量的方法,用户表,并使用数据透视表中的注释行,就看你了。


希望我能向您澄清这个问题。

  • 谢谢,对我有用:) (3认同)
  • 谢谢你。你救了我的命。按照您的解释,我按照您的建议将外键更改为 bigInteger。`Schema::table('goal_objective', function (Blueprint $table) { $table->bigInteger('job_title_id')->after('target')->unsigned()->nullable(); $table-> foreign('job_title_id')->references('id')->on('job_titles')->onDelete('set null'); }` 成功了,谢谢。 (2认同)

Dan*_*ele 19

在我的情况下,问题在于该users表的自动生成的迁移正在设置

...
$table->bigIncrements('id');
...
Run Code Online (Sandbox Code Playgroud)

所以我不得不改变列的类型


$table->bigInteger('id');
Run Code Online (Sandbox Code Playgroud)

使我可以使用外键工作进行迁移。

这与laravel 5.8.2

  • 这为我工作$ table-> unsignedBigInteger('user_id'); 在laravel 5.8。*中 (9认同)

Vic*_*cky 16

在我的情况下,问题在于迁移时间要小心,而创建迁移首先创建子迁移而不是基本迁移.因为如果您首先创建基本迁移,您的外键将查找子表,并且不会有表,然后抛出异常.

更多:

创建迁移时,它的开头有一个时间戳.假设你已经创建了一个迁移,它看起来就像2015_08_19_075954_the_cats_time.php是这样的代码

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class TheCatsTime extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('cat', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');  
            $table->date('date_of_birth');
            $table->integer('breed_id')->unsigned()->nullable(); 
        });

        Schema::table('cat', function($table) {
        $table->foreign('breed_id')->references('id')->on('breed');
      });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('cat');
    }
}
Run Code Online (Sandbox Code Playgroud)

在创建基表后,您将创建另一个迁移品种,即子表,它具有自己的创建时间和日期戳.代码如下所示:

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class BreedTime extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('breed', function (Blueprint $table) {
             $table->increments('id');    
             $table->string('name');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('breed');
    }
}
Run Code Online (Sandbox Code Playgroud)

看来这两个表都是正确的但是当你运行php artisan migrate时.它会引发异常,因为迁移将首先在数据库中创建基表,因为您先创建了此迁移,并且我们的基表中有外键约束,它将查找子表并且子表不存在,这可能是例外......

所以:

首先创建子表迁移.

创建子迁移后创建基表迁移.

php工匠迁移.

完成它会工作


小智 13

在我的情况下,我只是更改手动执行迁移的顺序,因此首先创建表用户.

在文件夹数据库/迁移/您的迁移文件名具有以下格式:year_month_day_hhmmss_create_XXXX_table.php

只需重命名创建用户文件,以便将表优先级表的创建日期设置为晚于用户日期(即使一秒钟后就足够了)


小智 9

我在使用Laravel 5.8时遇到了同样的问题在仔细研究了laravel文档之后,这里还有Migrations&bigIncrements。我解决问题的方法是在与表“ users”及其关联相关的每个表中添加主键“ $ table-> bigIncrements('id')”,在本例中为表“ role”。最后,我有“ $ table-> unsignedBigInteger”用于将角色与用户(多对多)相关联,即表“ role_user”

1. Users table

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

2. Roles Table
    Schema::create('roles', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('name')->unique();
        $table->string('display_name')->nullable();
        $table->string('description')->nullable();
        $table->timestamps();
    });

3. Table role_user
Schema::create('role_user', function (Blueprint $table) {
            $table->unsignedBigInteger('user_id');
            $table->unsignedBigInteger('role_id');
            $table->foreign('user_id')->references('id')->on('users')
                ->onUpdate('cascade')->onDelete('cascade');
            $table->foreign('role_id')->references('id')->on('roles')
                ->onUpdate('cascade')->onDelete('cascade');
            $table->primary(['user_id', 'role_id']);
        });
Run Code Online (Sandbox Code Playgroud)


小智 9

在laravel 5.8中,users_table使用bigIncrements('id')数据类型作为主键。这样,当您要引用外键约束时,user_id需要unsignedBigInteger('user_id')输入列。


小智 7

这个错误发生在我身上,因为 - 虽然我试图创建的表是 InnoDB - 我试图将它关联到的外部表是 MyISAM 表!


Sly*_*tor 7

我在laravel 5.8中遇到了这个问题,并将此代码添加到我添加user_id的地方。

$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
Run Code Online (Sandbox Code Playgroud)

然后我跑了 $ php artisan migrate:refresh


小智 6

你应该这样写

public function up()
{
    Schema::create('transactions', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->float('amount', 11, 2);
        $table->enum('transaction type', ['debit', 'credit']);
        $table->bigInteger('customer_id')->unsigned();      
        $table->timestamps();                 
    });

    Schema::table('transactions', function($table) {
        $table->foreign('customer_id')
              ->references('id')->on('customers')
              ->onDelete('cascade');
    });     
}
Run Code Online (Sandbox Code Playgroud)

外键字段应该是unsigned,希望它有帮助!!


bmn*_*ali 5

为了在 Laravel 中添加外键约束,以下内容对我有用:

  1. 创建作为外键的列,如下所示:

    $table->integer('column_name')->unsigned();
  2. 立即在 (1) 之后添加约束线,即

    $table->integer('column_name')->unsigned();
    $table->foreign('column_name')->references('pk_of_other_table')->on('other_table');


pav*_*mar 5

除非创建相关表,否则我们无法添加关系。Laravel按迁移文件的日期运行迁移顺序。因此,如果要与第二个迁移文件中存在的表创建关系,它将失败。

我遇到了同样的问题,因此我最后又创建了一个迁移文件来指定所有关系。

Schema::table('properties', function(Blueprint $table) {
        $table->foreign('user')->references('id')->on('users')->onDelete('cascade');
        $table->foreign('area')->references('id')->on('areas')->onDelete('cascade');
        $table->foreign('city')->references('id')->on('cities')->onDelete('cascade');
        $table->foreign('type')->references('id')->on('property_types')->onDelete('cascade');
    });

    Schema::table('areas', function(Blueprint $table) {
        $table->foreign('city_id')->references('id')->on('cities')->onDelete('cascade');
    });
Run Code Online (Sandbox Code Playgroud)


Rad*_*iță 5

使用Laravel 5.3存在相同的问题。

解决方案是使用unsignedInteger而不是integer('name')-> unsigned()

所以这是有效的

$table->unsignedInt('column_name');
$table->foreign('column_name')->references('id')->on('table_name');
Run Code Online (Sandbox Code Playgroud)

起作用的原因是,当使用integer('name')-> unsigned时,表中创建的列的长度为11,而当使用unsigedInteger('name')时,列的长度为10。

长度10是使用Laravel时主键的长度,因此列的长度匹配。


bno*_*afk 5

请注意:当 Laravel 使用

$table->increments('id');
Run Code Online (Sandbox Code Playgroud)

这是大多数迁移的标准,这将设置一个无符号整数字段。因此,当从另一个表对该字段进行外部引用时,请确保在引用表中将该字段设置为 UnsignedInteger 而不是(我认为是)UnsignedBigInteger 字段。

例如:在迁移文件 2018_12_12_123456_create_users_table.php 中:

Schema::create('users', function (Blueprint $table){
    $table->increments('id');
    $table->string('name');
    $table->timestamps();
Run Code Online (Sandbox Code Playgroud)

然后在迁移文件 2018_12_12_18000000_create_permissions_table.php 中,将外部引用设置回用户:

Schema::create('permissions', function (Blueprint $table){
    $table->increments('id');
    $table->UnsignedInteger('user_id'); // UnsignedInteger = "increments" in users table
    $table->boolean('admin');
    $table->boolean('enabled');
    $table->timestamps();

    // set up relationship
    $table->foreign('user_id')->reference('id')->on('users')->onDelete('cascade');
}
Run Code Online (Sandbox Code Playgroud)


Mr.*_*ist 5

2021 年 4 月 20 日

在 Laravel 8 中我遇到了这个问题。如果您不使用nullable(),则可能会发生此错误。

$table->bigInteger('user_id')->nullable()->unsigned()->index();
$table->foreign('user_id')->references('id')->on('users')->onUpdate('cascade')->onDelete('set null');
Run Code Online (Sandbox Code Playgroud)