我应该在外键上使用 onDelete=cascade 吗?
Posted
技术标签:
【中文标题】我应该在外键上使用 onDelete=cascade 吗?【英文标题】:Should I be using onDelete=cascade with my foreign keys? 【发布时间】:2021-10-29 14:34:19 【问题描述】:相关问题:Foreign key constraints: When to use ON UPDATE and ON DELETE。
我们举个例子,一个公司表和一个用户表,其中包含来自这些公司的人
CREATE TABLE COMPANY (
company_id INT NOT NULL,
company_name VARCHAR(50),
PRIMARY KEY (company_id)
) ENGINE=INNODB;
CREATE TABLE USER (
user_id INT,
user_name VARCHAR(50),
company_id INT,
INDEX company_id_idx (company_id),
FOREIGN KEY (company_id) REFERENCES COMPANY (company_id) ON...
) ENGINE=INNODB;
ON DELETE CASCADE:危险:如果您删除表 COMPANY 中的公司行,引擎也会删除相关的 USER。这很危险,但可用于对辅助表进行自动清理(因此它可以是您想要的,但肯定不是 COMPANYUSER 示例)
现在,假设我有多家公司,每家公司都有多个客户。我习惯在每个表上都有一个主自动索引键,并将其用作子表的外键。
那么,既然我的company_id
是自动生成的并且保证是唯一的,那么我将用户表中的外键company_id
设置为onDelete=cascade 有什么危险吗?
显然,我的 GUI 有很多“你确定你确定你真的要删除它吗?操作无法撤消!”
但是,如果我不 onDelete=cascade,那么在我可以DELETE FROM companies WHERE company_id=X
之前,我首先必须DELETE FROM users WHERE company_id=X
,这是我一直在做的事情。
我第一次考虑 onDelete=cascade 只是想确定我已经理解了它。当依赖关系树有多个层次时,删除依赖行可能会变得乏味。
另外,由于键是自动索引,它们不会改变,所以我看不出我需要 onUpdate。
[更新] 一个答案是关于删除业务数据。这只是相关问题中的一个示例。
想象一下架构:一个用户可以有多个站点的平面图,每个站点有多个建筑物,每个有多个楼层,每个有多个房间。
它是一个级联的、树状的层次结构。在那里有 onDelete=Cascade 有意义吗?我想是的,但想听听那些更有知识的人的意见
【问题讨论】:
【参考方案1】:这很大程度上取决于您的具体用例。由于您无论如何都在尝试删除用户,并且您希望它作为清理的一部分自动发生,因此对我来说似乎是使用 ON DELETE 的不错选择。
不过,我可能不会删除这些记录。我将停用它们,将公司设置为非活动状态。然后 ON UPDATE 将是一个很好的候选,它将非活动状态级联到公司的所有用户。
我会犹豫是否要删除,原因有两个:
首先,如果公司返回,这可以让您恢复您想要的部件以便更快地设置。如果公司被错误删除,则不太可能触发从备份恢复。
其次,我假设这些实体也会传播到其他表中。我不想仅仅因为我们不再有活跃的关系就删除客户/供应商的订单历史记录。即使您不从这些其他表中删除记录,您最终也可能会在这些记录中孤立 companyId/userId。
【讨论】:
感谢您的精彩回答 (+1)。我只是使用了一个相关问题中的示例,该问题恰好是关于商业的。我的应用更像是创建了一个组织结构图。或者,想象一下建筑:一个用户可以有多个站点的计划,每个站点有多个建筑物,每个有多个楼层,每个有多个房间。我将更新问题以反映这一点。你现在怎么想?以上是关于我应该在外键上使用 onDelete=cascade 吗?的主要内容,如果未能解决你的问题,请参考以下文章
如何在一对一关系中使用 onDelete: 'CASCADE'
Laravel 迁移:从现有外键中删除 onDelete('cascade')
OnDelete(DeleteBehavior.Cascade) 可能会导致循环或多个级联路径
Laravel 外键 onDelete('cascade') 不起作用