您好我在使用迁移架构构建器创建表时遇到问题。 使用自引用外键的表发生此问题。 以下是产生错误的代码:
Schema::create('cb_category', function($table)
{
$table->integer('id')->primary()->unique()->unsigned();
$table->integer('domain_id')->unsigned();
$table->foreign('domain_id')->references('id')->on('cb_domain');
$table->integer('parent_id')->nullable();
$table->foreign('parent_id')->references('id')->on('cb_category')->onUpdate('cascade')->onDelete('cascade');
$table->string('name');
$table->integer('level');
});
这是错误:
SQLSTATE[HY000]: General error: 1005 Can't create table 'eklik2.#sql-7d4_e' (errno: 150) (SQL: alter table `cb_cate
del上的 gory add constraint cb_category_parent_id_foreign foreign key (
parent_id ) references
cb_category (
id`)
更新级联上的ete级联)(绑定:数组(
))
[PDOException] SQLSTATE [HY000]:常规错误:1005无法创建表'eklik2。#sql-7d4_e'(错误号:150)
有什么想法吗?
答案 0 :(得分:8)
你必须把它分成两个Schema块,一个创建列,另一个添加FK。 mysql不能同时做到这两点。
答案 1 :(得分:4)
我可能为聚会太迟了,但官方文件声称外键,如果是整数,必须是->unsigned();
http://laravel.com/docs/4.2/schema#foreign-keys
注意:创建引用递增的外键时 整数,记得始终使外键列无符号。
另外,如果你(因为我)拼错unsigned()
并且我花了几个小时试图弄清楚为什么没有创建密钥,Artisan不会失败。
所以有两件事:
1.在递增整数的情况下,始终使外键列无符号
2.检查unsigned()
答案 2 :(得分:1)
Schema::create('cb_category', function (Blueprint $table) {
$table->increments('id')->unsigned();
$table->integer('domain_id')->unsigned();
$table->foreign('domain_id')->references('id')->on('cb_domain');
$table->integer('parent_id')->nullable();
$table->foreign('parent_id')->references('id')->on('cb_category')->onUpdate('cascade')->onDelete('cascade');
$table->string('name');
$table->integer('level');
});
试试这个
答案 3 :(得分:1)
两个查询有效:
Schema::create('cb_category', function($table)
{
$table->integer('id')->primary()->unique()->unsigned();
$table->integer('parent_id')->nullable();
});
Schema::table('cb_category', function (Blueprint $table)
{
$table->foreign('parent_id')->references('id')->on('cb_category')->onUpdate('cascade')->onDelete('cascade');
});
答案 4 :(得分:0)
我认为您有另一个表,该表引用了您要创建的当前表。 我遇到了这个问题,删除了那个表,问题就解决了
答案 5 :(得分:0)
Laravel还提供了对创建外键约束的支持,这些外键约束用于强制数据库级别的参照完整性。例如,让我们在 posts 表上定义一个 user_id 列,该列引用 users 表上的 id 列:
Schema::table('posts', function (Blueprint $table) {
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');
});
由于此语法相当冗长,因此Laravel提供了其他的,更简短的方法,这些方法使用约定来提供更好的开发人员体验。上面的示例可以这样写:
Schema::table('posts', function (Blueprint $table) {
$table->foreignId('user_id')->constrained();
});
foreignId
方法是unsignedBigInteger
的别名,而受约束的方法将使用约定来确定所引用的表和列的名称。如果表名不符合约定,则可以通过将表名作为参数传递给constrained
方法来指定表名:
Schema::table('posts', function (Blueprint $table) {
$table->foreignId('user_id')->constrained('users');
});
您还可以为约束的"on delete"
和"on update"
属性指定所需的操作:
$table->foreignId('user_id')
->constrained()
->onDelete('cascade');
必须在constrained
之前调用其他column modifiers:
$table->foreignId('user_id')
->nullable()
->constrained();
要删除外键,可以使用dropForeign
方法,将要删除的外键约束作为参数传递。外键约束根据表名和约束中的列使用与索引相同的命名约定,后跟"_foreign"
后缀:
$table->dropForeign('posts_user_id_foreign');
或者,您可以将包含保留有外键的列名的数组传递给dropForeign
方法。数组将使用Laravel模式构建器使用的约束名称约定自动转换:
$table->dropForeign(['user_id']);
您可以使用以下方法在迁移过程中启用或禁用外键约束:
Schema::enableForeignKeyConstraints();
Schema::disableForeignKeyConstraints();
SQLite默认情况下禁用外键约束。使用SQLite时,请确保在数据库配置中启用外键支持,然后再尝试在迁移中创建外键支持。另外,SQLite仅在创建表时才支持外键,而在表被更改时则不支持。
答案 6 :(得分:0)
对于 Laravel 8 ,反应也较晚,但可能更习惯惯用:
use App\Models\CbCategory;
...
Schema::create("cb_category", function(Blueprint $table)
{
$table->id();
$table->foreignIdFor(CbCategory::class, "parent_id")
->cascadeOnUpdate()
->cascadeOnDelete()
->nullable();
});
请注意:我猜这里是
CbCategory
的类名。直接使用类引用(而不是以前的表名称字符串)使您的静态代码检查器可以接管将来的类名称更改。
此外,_id
列名称的parent_id
后缀也很重要。
愿以下资源能使您渴望知识:
id()
:https://laravel.com/docs/8.x/migrations#column-method-id foreignIdFor()
:https://laravel.com/api/8.x/Illuminate/Database/Schema/Blueprint.html cascadeOnDelete()
和cascadeOnUpdate()
:https://laravel.com/api/8.x/Illuminate/Database/Schema/ForeignKeyDefinition.html