Php Laravel迁移自引用外键问题
您好,我在使用迁移架构生成器创建表时遇到问题。 具有自引用外键的表出现问题。 以下是产生错误的代码:Php Laravel迁移自引用外键问题,php,mysql,foreign-keys,migration,laravel,Php,Mysql,Foreign Keys,Migration,Laravel,您好,我在使用迁移架构生成器创建表时遇到问题。 具有自引用外键的表出现问题。 以下是产生错误的代码: Schema::create('cb_category', function($table) { $table->integer('id')->primary()->unique()->unsigned(); $table->integer('domain_id')->unsigned();
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
gory添加约束cb\u category\u parent\u id\u外键(
parent\u id)引用del上的cb\u category(
id`)
ete在更新级联时级联)(绑定:数组(
))
[例外情况]
SQLSTATE[HY000]:一般错误:1005无法创建表“eklik2.#sql-7d4_e”(错误号:150)
有什么想法吗?您必须将其分成两个模式块,一个创建列,另一个添加FK。mysql不能同时做这两件事。我可能来不及参加聚会了,但官方文件声称,如果是整数,外键必须是->unsigned()代码>
注意:当创建一个引用递增
整数,请记住始终使外键列无符号
另外,如果您(正如我一样)拼错了unsigned()
,Artisan也不会失败,我花了好几个小时试图弄清楚为什么没有创建密钥
所以有两件事:
1.在整数递增的情况下,始终使外键列无符号
2.检查unsigned()的拼写
试试这两个查询:
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');
});
我认为您有另一个表,它引用了您要创建的当前表。
我遇到了这个问题,并移除了那张表,我的问题就解决了Laravel 8
Laravel还支持创建外键约束,用于在数据库级别强制实现引用完整性。例如,让我们在posts表中定义一个用户id列,该列引用用户表中的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();
});
foreignd
方法是unsignedbiginger
的别名,而约束方法将使用约定来确定引用的表和列名。如果表名与约定不匹配,可以通过将表名作为参数传递给constrated
方法来指定表名:
Schema::table('posts', function (Blueprint $table) {
$table->foreignId('user_id')->constrained('users');
});
您还可以为约束的“on delete”
和“on update”
属性指定所需的操作:
$table->foreignId('user_id')
->constrained()
->onDelete('cascade');
必须在约束
之前调用任何附加命令:
$table->foreignId('user_id')
->nullable()
->constrained();
要删除外键,可以使用dropForeign
方法,将要删除的外键约束作为参数传递。基于表名和约束中的列,外键约束使用与索引相同的命名约定,后跟“\u Foreign”
后缀:
$table->dropForeign('posts_user_id_foreign');
或者,您可以将包含保存外键的列名的数组传递给dropForeign
方法。数组将使用Laravel的模式生成器使用的约束名称约定自动转换:
$table->dropForeign(['user_id']);
您可以使用以下方法在迁移中启用或禁用外键约束:
Schema::enableForeignKeyConstraints();
Schema::disableForeignKeyConstraints();
默认情况下,SQLite禁用外键约束。使用SQLite时,在迁移中尝试创建外键之前,请确保在数据库配置中启用外键支持。此外,SQLite仅在创建表时支持外键,而在更改表时不支持外键
也是一种迟来的反应,但可能是一种更为惯用的方式,用于Laravel 8:
使用App\Models\CbCategory;
...
模式::创建(“cb_类别”,函数(Blueprint$表)
{
$table->id();
$table->ForeigndFor(CbCategory::class,“父id”)
->级联更新()
->级联删除()
->可空();
});
请注意:我在这里猜到了CbCategory
的类名。使用类引用第一手资料(而不是以前的表名字符串)可以让静态代码检查器在将来的类名更改中进行检查。
此外,父id
列名处的\u id
-后缀也很重要
愿以下资源能满足您的求知欲:
id()
:
foreigndfor()
:
cascadeOnDelete()
&cascadeOnUpdate()
:
我把它分成了两条语句,但错误仍然存在:Schema::create(…);Schema::table('cb_category',function($table){$table->foreign('parent_id')->references('id')->on('cb_category')->onUpdate('cascade')->onDelete('cascade');};用断裂来解决。代码如下:Schema::create('cb_category',function($table){…})$dbh=DB::getPdo()$dbh->query(“ALTER TABLE cb_category ADD CONSTRAINT fk_cb_category\u parent_id外键(parent_id)在删除时引用cb_category(id)在更新时不执行任何操作”);这与问题中的问题相同。无法使表在创建时引用自身,因为在创建表时不存在要引用的表,这并不能回答问题。另外,这只是文件的复制+粘贴,每个人都可以自己阅读。这似乎是正确的答案。工作很好,很有意义。
Schema::enableForeignKeyConstraints();
Schema::disableForeignKeyConstraints();