迁移:无法在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_project
和project_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中增加外键约束,下面的工作对我来说是:
-
创build列为外键如下:
$表 - >整数( '列名') - >无符号();
-
在(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表格范围