mysql Laravel Schema onDelete set default

46scxncf  于 2023-06-21  发布在  Mysql
关注(0)|答案(3)|浏览(131)

我有两个表,它们具有一对一的关系,由外键约束设置。我想将onDelete规则设置为“setdefault”,这意味着当删除外部表上的一行时,引用值将恢复为其默认值。下面是我的代码:
图尔斯表:

Schema::create('tours', function (Blueprint $table) {
    $table->increments('id')->unsigned()->index();
    $table->integer('grade')->unsigned()->default(1);
    $table->timestamps();
});

等级表:

Schema::create('grades', function(Blueprint $table){
    $table->increments('id')->unsigned()->index();
    $table->string('name');
    $table->timestamps();
});

设置外键:

Schema::table('tours', function (Blueprint $table) {
    $table->foreign('grade')->references('id')->on('grades')->onDelete('set default');
});

当我运行我的迁移时,它工作正常-没有错误。然而,看看HeidiSQL中的表,它并没有正常工作;外键已设置,但onDelete属性仅显示“NO ACTION”。
随后,当我删除等级表中的一行时,我得到一个外键约束错误。
我做错了什么?

bqucvtff

bqucvtff1#

已经有一段时间了但是...这取决于您的数据库使用的引擎。如果使用InnoDBNDB语法将被解析但被忽略
查看MySQL文档的这一节:

引用动作

...
SET DEFAULT:MySQL解析器可以识别此操作,但InnoDBNDBreject包含ON DELETE SET DEFAULTON UPDATE SET DEFAULT子句的表定义。
你可以使用SET NULL来代替它,以满足你的需要。如果没有,那么您可以创建一个观察者来为您执行此操作。

xvw2m8pv

xvw2m8pv2#

这是工作解决方案。
首先设置外键引用,不带任何约束。
下面是迁移的代码:
$table->foreignId('category_id');
然后在该模型上设置删除模型事件并更新每个相关模型:
在这里,我更新category_id1,这是默认类别,并命名为未分类,这不能删除。
Category::deleting(function ($category) {
$recipe_ids = $category->recipes->pluck('id');
Recipe::whereIn('id', $recipe_ids)->update(['category_id' => 1]);
});

kzmpq1sx

kzmpq1sx3#

我只是来这里寻找相同的答案,我检查了文档,同时找到任何方法来直接管理删除外键,并设置一个默认值。不幸的是,我找不到一个直接的方法来做到这一点,但据我所知,有一种方法可以在模型观察者的帮助下做到这一点。我相信它可以工作的方式(尽管它有点乏味,并且用2个查询而不是1个查询来完成这项工作,这有点低效),基本上是在哪里
1.必须使外键属性可为空

$table->unsignedBigInteger("grade")->nullable();

1.您可以设置on delete函数将值设置为null,而不是级联

$table->foreign("grade")->references("id")->on("grades")->onDelete("set null");

1.在给定迁移的模型上,您必须设置一个观察者

public static function boot() {
    parent::boot();
    self::updating(function(Tour $tour) {
        if($tour->isDirty('grade')) {
            $tour->grade = [DEFAULT VALUE HERE];
        }
    });
}

这应该能够在删除成绩时将该值设置为默认值。
注意:这不是最有效的方法,我不能确认这是否是唯一的方法,这是我认为它可以工作的方式,我用过,这是我知道如何做到这一点的最好方法我仍然是一个新手程序员,如果有更好的方法来做,请随时提到我。

相关问题