我试图在Laravel中创建外键但是当我使用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');
}
关于我做错了什么的任何想法,我想立即做到这一点,因为我有很多我需要创建的表格,例如用户,客户,项目,任务,状态,优先级,类型,团队。理想情况下,我想创建使用外键保存此数据的表,即clients_project
和project_tasks
等。
希望有人可以帮助我开始。
提前致谢。
答案 0 :(得分:284)
分两步添加它,也可以将它设为无符号:
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');
});
}
答案 1 :(得分:92)
问题已经回答,但希望这可能有助于其他人。
我发生了这个错误,因为我在密钥作为主要原始表中的主键存在之前,先创建了带有外键的迁移表。迁移按创建顺序执行,如运行migrate:make
后生成的文件名所示。例如。 2014_05_10_165709_create_student_table.php
。
解决方案是使用外键将文件重命名为比使用主键的文件更早的时间:http://forumsarchive.laravel.io/viewtopic.php?id=10246
我想我还必须添加$table->engine = 'InnoDB';
答案 2 :(得分:41)
在我的情况下,问题是主表已经有记录,我强迫新列不是NULL。因此,在新列中添加 - > nullable()就可以了。在问题的例子中会是这样的:
$table->integer('user_id')->unsigned()->nullable();
或:
$table->unsignedInteger('user_id')->nullable();
希望这有助于某人!
答案 3 :(得分:14)
在我的情况下,问题在于迁移时间在创建迁移时要小心,首先创建子迁移而不是基本迁移。因为如果您先创建基本迁移,那么您的外键将查找子表,并且不会有表格然后抛出异常。
更多:
创建迁移时,它的开头有一个时间戳。假设你已经创建了一个迁移 cat ,所以它看起来像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');
}
}
创建基表后,您创建另一个迁移品种,这是子表,它有自己的创建时间和日期戳。 代码如下:
<?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 migrate 时。它会引发异常,因为迁移将首先在数据库中创建基表,因为您先创建了此迁移,并且我们的基表中有外键约束,它将查找子表并且子表不存在,这可能是例外..
<强>所以:强>
首先创建子表迁移。
创建子迁移后创建基表迁移。
php artisan migrate。
完成它将起作用
答案 4 :(得分:12)
在我的情况下,问题是users
表的自动生成的迁移正在设置
...
$table->bigIncrements('id');
...
所以我不得不更改列类型
$table->bigInteger('id');
使用外键进行迁移。
使用laravel 5.8.2
答案 5 :(得分:12)
就我而言,我只是更改了手动执行迁移的顺序,因此首先创建表用户。
在文件夹数据库/迁移中/您的迁移文件名具有以下格式: year_month_day_hhmmss_create_XXXX_table.php
只需重命名创建用户文件,以便将表优先级表的创建日期设置为晚于用户日期(即使后一秒就足够了)
答案 6 :(得分:7)
我在laravel 5.8中遇到了这个问题,并将此代码添加到我添加user_id的地方。
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
然后我跑了$ php artisan migrate:refresh
答案 7 :(得分:5)
我在使用 Laravel 5.8时遇到了同样的问题。在仔细研究了laravel文档之后,这里Migrations & bigIncrements。我解决该问题的方法是向与表“用户” 相关的每个表中添加主键“ $ table-> bigIncrements('id')” 它的关联,在我的例子中是表“角色” 。最后,我有“ $ 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']);
});
答案 8 :(得分:5)
As of Laravel 5.8,迁移存根在ID上使用bigIncrements方法 默认情况下为列。以前,ID列是使用 增量法。
这不会影响您项目中的任何现有代码;但是 请注意,外键列必须是同一类型。因此, 使用增量方法创建的列无法引用 使用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();
});
}
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('board_id')->unsigned()->index(); // this is working
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
如您所见,注释行将引发查询异常,因为如升级说明中所述,外键列必须为同一类型,因此您需要更改在 role_user 表中指向 bigInteger 的键(在此示例中为 user_id ),或将 bigIncrements 方法更改为 users 表中的增量方法并使用数据透视表中的注释行,这取决于您。
我希望我能向您澄清这个问题。
答案 9 :(得分:5)
在laravel 5.8中,users_table使用LoginResult
数据类型作为主键。因此,当您要引用外键约束时,您的bigIncrements('id')
列必须为user_id
类型。
答案 10 :(得分: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');
});
答案 11 :(得分:4)
使用Laravel 5.3也有同样的问题。
解决方案是使用 unsignedInteger 而不是整数('name') - &gt; unsigned()。
这就是有效的方法
$table->unsignedInt('column_name');
$table->foreign('column_name')->references('id')->on('table_name');
这样做的原因是,当使用整数('name') - &gt; unsigned 时,表中创建的列的长度为11,但使用 unsigedInteger('name)时')该列的长度为10.
长度10是使用Laravel时主键的长度,因此列长度匹配。
答案 12 :(得分:4)
为了在laravel中添加外键约束,以下内容对我有用:
将列创建为外键,如下所示:
$table->integer('column_name')->unsigned();
在(1)之后立即添加约束线,即
$table->integer('column_name')->unsigned(); $table->foreign('column_name')->references('pk_of_other_table')->on('other_table');
答案 13 :(得分:3)
我知道这是一个老问题,但要确保你是否正在使用引用,定义了正确的支持引擎。为两个表设置innodb引擎,为参考列设置相同的数据类型
$table->engine = 'InnoDB';
答案 14 :(得分:3)
您应该以这种方式写
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');
});
}
外键字段应未签名,希望对您有所帮助!
答案 15 :(得分:3)
请注意:当Laravel使用设置表格时
$table->increments('id');
(在大多数迁移中是标准配置),这将设置一个无符号整数字段。因此,当从另一个表对该字段进行外部引用时,请确保在引用表中将字段设置为UnsignedInteger而不是UnsignedBigInteger字段(我认为是该字段)。
例如:在迁移文件2018_12_12_123456_create_users_table.php中:
Schema::create('users', function (Blueprint $table){
$table->increments('id');
$table->string('name');
$table->timestamps();
然后在迁移文件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');
}
答案 16 :(得分:2)
在原始问题的几年后,使用laravel 5.1,我遇到了同样的错误,因为我的迁移是使用所有相同的日期代码进行计算机生成的。我查看了所有提出的解决方案,然后重构以找到错误源。
在以下的laracasts中,在阅读这些帖子时,我认为正确的答案类似于Vickies的答案,除了您不需要添加单独的架构调用。你不需要将表设置为Innodb,我假设laravel正在这样做。
迁移只需要正确计时,这意味着您将在需要外键的表的文件名中修改(稍后)日期代码。或者或另外,降低不需要外键的表的日期代码。
修改日期代码的好处是您的迁移代码更易于阅读和维护。
到目前为止,我的代码正在通过调整时间代码来推迟需要外键的迁移。
但是我确实有数百个表,所以最后我只有一个外键表。只是为了让事情顺利进行。我假设我会把它们拉到正确的文件中并修改日期代码,因为我测试它们。
一个例子:文件2016_01_18_999999_create_product_options_table。这个需要创建产品表。查看文件名。
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的模型编写测试时重构。当我把它们拉出来时,这些键被评论,但你明白了。
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');
// });
答案 17 :(得分:2)
确保你的前列专栏远远超出了前列关键栏
我的意思是你的foreingkey(在第二个表中)必须是你的ponter主键的相同类型(在第一个表中)
你的指针主键必须添加unsigned方法,让我显示:
第一个迁移表上的:
$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');
另一个看待差异的例子
第一个迁移表上的:
$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');
答案 18 :(得分:2)
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');
答案 19 :(得分:2)
这个错误发生在我身上,因为 - 虽然我试图创建的表是InnoDB - 我试图将它与之关联的外表是一个MyISAM表!
答案 20 :(得分:1)
(学习英语,抱歉) 我在我的项目中尝试使用“foreignId”并工作。在您的代码中,只需删除列 user_id 并在引用中添加 foreignId:
public function up()
{
Schema::create('priorities', function($table) {
$table->increments('id', true);
$table->foreignId('user_id')->references('id')->on('users');
$table->string('priority_name');
$table->smallInteger('rank');
$table->text('class');
$table->timestamps('timecreated');
});
}
重要提示:在这种情况下,首先创建没有外键的表,即“用户”表
答案 21 :(得分:1)
对我来说,问题是一个旧表正在使用MyISAM而不是InnoDB。这样就解决了
$tables = [
'table_1',
'table_2'
];
foreach ($tables as $table) {
\DB::statement('ALTER TABLE ' . $table . ' ENGINE = InnoDB');
}
答案 22 :(得分:1)
有时此错误可能是由于迁移顺序而引起的。
“用户”和“订单”是两个表
订单表中有用户的外键 (在迁移过程中,如果先迁移Order表,则将引起问题,因为没有用户匹配外键)
解决方案: 只需将您的“订单更新”表放在要更新的用户下方
示例: 就我而言,教育和大学表 教育表
public function up()
{
Schema::create('doc_education', function (Blueprint $table) {
$table->increments('id');
$table->integer('uni_id')->unsigned()->nullable();
$table->timestamps();
});
}
在大学里
Schema::create('doc_universties', function (Blueprint $table) {
$table->increments('id');
$table->string('uni_name');
$table->string('location')->nullable();
$table->timestamps();
//
});
Schema::table('doc_education', function(Blueprint $table) {
$table->foreign('uni_id')->references('id')
->on('doc_universties')->onDelete('cascade');
});
答案 23 :(得分:1)
另一个原因可能是数据库引擎类型。 Laravel 默认使用 MyISAM 引擎。所以如果你需要强制执行外键引用检查,你应该使用 InnoDB 作为你的引擎。
此设置在您的 config/database.php
文件中。将引擎更改为 'engine' => 'InnoDB'
此外,如果您尝试对现有表执行此操作,请使用
更改引擎DB::statement("ALTER TABLE `{$tableName}` ENGINE = 'InnoDB'");
答案 24 :(得分:1)
如果以上解决方案都不适用于新手,请检查两个ID是否具有相同的类型:integer
或两者都是bigInteger
,......您可以这样:
主表(例如用户)
$table->bigIncrements('id');
子表(例如优先级)
$table->unsignedInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
此查询将失败,因为users.id
为BIG INTEGER
而priorities.user_id
为INTEGER
。
在这种情况下,正确的查询如下:
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
答案 25 :(得分:1)
这也可能是您创建迁移的顺序。如果先创建优先级表,然后再创建用户表,那将是错误的。由于第一次迁移,正在寻找用户表。因此,您必须更改
上的迁移顺序 #showcase {
background: url(../img/showcase.jpg) no-repeat top center fixed/cover ;
position: relative;
min-height: 650px;
color: #fff;
padding-top: 6rem; }
#showcase .home-search {
min-height: 400px;
position: relative;
border-radius: 5px; }
#showcase .overlay {
content: '';
position: absolute;
top: 0;
left: 0;
min-height: 400px;
width: 100%;
background: rgba(51, 51, 51, 0.8); }
目录
答案 26 :(得分:1)
就我而言,直到我运行命令,该命令才起作用
5000
那样,您可以将外键保留在创建模式之内
composer dump-autoload
答案 27 :(得分:1)
你可以直接在整数列中传递布尔参数,说它应该是无符号的。在laravel 5.4下面的代码解决了我的问题。
$table->integer('user_id', false, true);
此处第二个参数 false 表示它不应自动递增,第三个参数 true 表示它应该是无符号的。您可以将外键约束保留在同一个迁移中或将其分开。它适用于两者。
答案 28 :(得分:1)
这么简单!!!
如果您的第一个创建'priorities'
迁移文件,则Laravel首先运行'priorities'
,而'users'
表不存在。
如何为不存在的表添加关系!。
解决方案:从'priorities'
表中提取 外键代码。您的迁移文件应如下所示:
并添加到新的迁移文件,此处其名称为create_prioritiesForeignKey_table
并添加以下代码:
public function up()
{
Schema::table('priorities', function (Blueprint $table) {
$table->foreign('user_id')
->references('id')
->on('users');
});
}
答案 29 :(得分:1)
就我而言,我在字符串 id
列上引用了整数 user_id
列。我改变了:
$table->string('user_id')
为:
$table->integer('user_id')->unsigned();
希望它有所帮助!
答案 30 :(得分:0)
对我来说,我的子表引用的表列未编制索引。
Schema::create('schools', function (Blueprint $table) {
$table->integer('dcid')->index()->unque();
$table->integer('school_number')->index(); // The important thing is that this is indexed
$table->string('name');
$table->string('abbreviation');
$table->integer('high_grade');
$table->integer('low_grade');
$table->timestamps();
$table->primary('dcid');
});
Schema::create('students', function (Blueprint $table) {
$table->increments('id');
$table->integer('dcid')->index()->unique()->nullable();
$table->unsignedInteger('student_number')->nullable();
$table->integer('schoolid')->nullable();
$table->foreign('schoolid')->references('school_number')->on('schools')->onDelete('set null');
// ...
});
忽略可怕的命名,它来自另一个设计糟糕的系统。
答案 31 :(得分:0)
我注意到的一件事是,如果表使用不同的引擎而不是外键约束,则不起作用。
例如,如果一个表使用:
$table->engine = 'InnoDB';
其他用途
$table->engine = 'MyISAM';
会产生错误:
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint
您可以通过在表创建结束时添加InnoDB来解决此问题,如下所示:
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedInteger('business_unit_id')->nullable();
$table->string('name', 100);
$table->foreign('business_unit_id')
->references('id')
->on('business_units')
->onDelete('cascade');
$table->timestamps();
$table->softDeletes();
$table->engine = 'InnoDB'; # <=== see this line
});
}
答案 32 :(得分:0)
我认为:引用键必须是“索引”。 例如:(下)
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');
});
}
祝你好运。
答案 33 :(得分:0)
要点是外来方法使用ALTER_TABLE
将预先存在的字段转换为外键。因此,您必须在应用外键之前定义表类型。但是,它不必单独进行Schema::
调用。您可以在create中执行这两项操作,如下所示:
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
的类型设置为unsigned以匹配外键。
答案 34 :(得分:0)
制作数据透视表时,Laravel 5出现了同样的错误,我的问题是我没有
->onDelete('cascade');
答案 35 :(得分:0)
我认为这里的答案中缺少一件事,如果我错了请纠正我,但外键需要在数据透视表上编入索引。至少在mysql中似乎就是这种情况。
NumberPicker
答案 36 :(得分:0)
请先检查列的数据类型。如果第一个表 id 类型是 bigint,那么在添加外键时检查其他表中的类型应该是 bigint。
答案 37 :(得分:0)
在自动创建的 create_users_table 迁移中,将 $table->id();
更改为 $table->increments('id');
。对我有用,希望能帮到你!
答案 38 :(得分:0)
捷径:
//内部架构::创建
$table->foreign('user_id')->bigInteger('user_id')->unsigned()->index();
//内部 Schema::table
$table->foreign('users_id')->references('id')->on('users')->onUpdate('cascade')->onDelete('cascade');
//处理您的代码。
public function up()
{
//
Schema::create('priorities', function($table) {
$table->increments('id', true);
$table->integer('user_id');
$table->foreign('user_id')->bigInteger('user_id')->unsigned()->index();
$table->string('priority_name');
$table->smallInteger('rank');
$table->text('class');
$table->timestamps('timecreated');
});
Schema::table('administrador', function($table) {
$table->foreign('users_id')->references('id')->on('users')
->onUpdate('cascade')
->onDelete('cascade');
;
});
}