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

我试图在Laravel中创build外键,但是当我使用artisan迁移我的表时,我抛出了以下错误:

 [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`)) 

我的迁移代码是这样的:

优先级迁移文件

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

用户迁移文件

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

任何想法,我做错了,我想现在得到这个,因为我有很多表,我需要创build例如用户,客户端,项目,任务,状态,优先级,types,团队。 理想情况下,我想创build表中保存这些数据的外键,我..客户clients_projectproject_tasks

希望有人能帮助我开始。

提前致谢。

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

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

问题已经回答,但希望这可以帮助别人。

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

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

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

在我的情况下,问题是主表已经在它的logging,我强迫新列不是NULL。 所以添加一个 – > nullable()到新列做了诀窍。 在问题的例子中是这样的:

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

要么:

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

希望这有助于某人!

在我的情况下,问题是迁移时间要小心,同时创build迁移首先创build子迁移比基础迁移。 因为如果你首先创build基类迁移,那么你的外键将会寻找子表,并且不会是抛出exception的表。

更多:

在创build迁移时,在开始时会有一个时间戳。 可以说你已经创build了一个迁移猫,所以它看起来像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'); } } 

创build基表后,您将创build另一个子表,它具有自己的创build时间和date标记。 代码将如下所示:

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

看来这两个表都是正确的,但是当你运行php artisan迁移 。 它会抛出一个exception,因为迁移将首先在您的数据库中创build基表,因为您先创build了这个迁移,而且我们的基表中有外键约束,它将查找子表并且子表不存在,一个例外..

所以:

首先创build子表迁移。

创build子迁移后创build基表迁移。

PHP的工匠迁移。

完成它将工作

在我的情况下,我只是改变顺序迁移手动执行,所以表用户首先创build。

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

只需重命名创build用户文件,以便您的表优先级表的创builddate设置晚于用户date(甚至一秒钟后就足够了)

为了在laravel中增加外键约束,下面的工作对我来说是:

  1. 创build列为外键如下:

      $表 - >整数( '列名') - >无符号(); 
  2. 在(1)之后立即添加约束行,即

      $表 - >整数( '列名') - >无符号();
     $表 - >外国( 'COLUMN_NAME') - >引用( 'pk_of_other_table') - >在( 'other_table'); 

除非创build相关表,否则我们不能添加关系。 Lareavel按迁移文件date运行迁移顺序。 所以如果你想创build一个存在于第二个迁移文件中的表的关系,它就会失败。

我面临同样的问题,所以我最后再创build一个迁移文件来指定所有的关系。

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

在原始问题之后的几年里,使用laravel 5.1,在同一个date代码的计算机生成的迁移中,我遇到了同样的错误。 我经历了所有提出的解决scheme,然后重构以find错误源。

在下面的laracasts中,并阅读这些post,我相信正确的答案是类似于Vickies的答案,除了你不需要添加一个单独的模式调用。 你不需要把表设置成Innodb,我假设laravel现在正在这样做。

迁移只需要正确的计时,这意味着你将修改date代码(以后)的文件名为你需要外键的表。 或者或另外,降低不需要外键的表的date代码。

修改date代码的优点是您的迁移代码将更易于阅读和维护。

到目前为止,我的代码正在通过调整时间码来推回需要外键的迁移。

不过,我有数百个表,所以最后我只有一个最后一个表,只是外键。 只是为了让事情stream畅。 我假设我将这些拉入正确的文件,并修改date代码,我testing他们。

举个例子:文件2016_01_18_999999_create_product_options_table。 这一个需要创build产品表。 看看文件名。

  public function up() { Schema::create('product_options', function (Blueprint $table) { $table->increments('id'); $table->integer('product_attribute_id')->unsigned()->index(); $table->integer('product_id')->unsigned()->index(); $table->string('value', 40)->default(''); $table->timestamps(); //$table->foreign('product_id')->references('id')->on('products'); $table->foreign('product_attribute_id')->references('id')->on('product_attributes'); $table->foreign('product_id')->references('id')->on('products'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('product_options'); } 

产品表:这需要先迁移。 2015_01_18_000000_create_products_table

 public function up() { Schema::create('products', function (Blueprint $table) { $table->increments('id'); $table->string('style_number', 64)->default(''); $table->string('title')->default(''); $table->text('overview')->nullable(); $table->text('description')->nullable(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::drop('products'); } 

最后,我暂时用来解决问题的文件,我将在我为9999_99_99_999999_create_foreign_keys.php命名的模型编写testing时重构这些文件。 这些键被评论,我把他们拉出来,但你明白了。

  public function up() { // Schema::table('product_skus', function ($table) { // $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade'); // }); } /** * Reverse the migrations. * * @return void */ public function down() { // Schema::table('product_skus', function ($table) // { // $table->dropForeign('product_skus_product_id_foreign'); // }); 

这个错误发生在我身上,因为 – 当我试图创build的表是InnoDB – 我试图将它与MyISAM表联系起来的外表!

使用Laravel 5.3也有同样的问题。

解决方法是使用unsignedInteger而不是整数('name') – > unsigned()

所以这是有效的

 $table->unsignedInt('column_name'); $table->foreign('column_name')->references('id')->on('table_name'); 

这个工作的原因是,当使用integer('name') – > unsigned在表中创build的列长度为11,但是当使用unsigedInteger('名称')列的长度为10。

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

在我的情况下,我引用了string user_id列上的整数 id列。 我变了:

$table->string('user_id')

至:

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

希望它可以帮助别人!

我知道这是一个古老的问题,但确保如果您正在参考适当的支持引擎的定义。 为两个表设置innodb引擎,为参考列设置相同的数据types

 $table->engine = 'InnoDB'; 

很简单 !!!

如果您第一次创build'priorities'迁移文件,则Laravel首先运行'priorities''users'表不存在。

它如何将关系添加到不存在的表!

解决scheme:从'priorities'表中提取 外键代码 。 你的迁移文件应该是这样的:

在这里输入图像描述

并添加到一个新的迁移文件,这里它的名字是create_prioritiesForeignKey_table并添加这些代码:

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

我认为有一件事从这里的答案是缺less的,如果我错了,请纠正我,但外键需要在数据透视表上索引。 至less在似乎是这样的情况下的MySQL。

 public function up() { Schema::create('image_post', function (Blueprint $table) { $table->engine = 'InnoDB'; $table->increments('id'); $table->integer('image_id')->unsigned()->index(); $table->integer('post_id')->unsigned()->index(); $table->timestamps(); }); Schema::table('image_post', function($table) { $table->foreign('image_id')->references('id')->on('image')->onDelete('cascade'); $table->foreign('post_id')->references('id')->on('post')->onDelete('cascade'); }); } 

在制作数据透视表时,我和Laravel 5有同样的错误,而我的问题是我没有

->onDelete('cascade');

在我的情况下,当我定义列时,我忘了使用括号->unsigned()

错误代码: $table->integer('permission_id')->unsigned; table- $table->integer('permission_id')->unsigned;

真正的代码: $table->integer('permission_id')->unsigned();

要点在于,外部方法使用ALTER_TABLE将预先存在的字段变成外键。 所以你必须在应用外键之前定义表types。 但是,它不必在单独的Schema::调用中。 你可以在创build中这样做:

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

另请注意, user_id的types设置为无符号以匹配外键。

我认为:参考键必须是“索引”。 例如:(下)

 public function up() { Schema::create('clicks', function (Blueprint $table) { $table->increments('id'); $table->string('viewer_id'); $table->integer('link_id')->index()->unsigned(); $table->string('time'); $table->timestamps(); }); Schema::table('clicks', function($table) { $table->foreign('link_id')->references('id')->on('links')->onDelete('cascade'); }); } 

祝你好运。

确保你的前列已经过去了

我的意思是你的foreignkey(在第二个表中)必须是你的pounter主键(在第一个表中)

你的指针主键必须加上无符号的方法,让我显示:

在您的FIRST迁移表上:

 $table->increments('column_name'); //is INTEGER and UNSIGNED 

在您的SECOND迁移表上:

 $table->integer('column_forein_name')->unsigned(); //this must be INTEGER and UNSIGNED $table->foreign('column_forein_name')->references('column_name')->on('first_table_name'); 

另一个例子,看到不同

在您的FIRST迁移表上:

 $table->mediumIncrements('column_name'); //is MEDIUM-INTEGER and UNSIGNED 

在您的SECOND迁移表上:

 $table->mediumInteger('column_forein_name')->unsigned(); //this must be MEDIUM-INTEGER and UNSIGNED $table->foreign('column_forein_name')->references('column_name')->on('first_table_name'); 

查看MYSQL数字types表格范围