我不是每天都设计模式,但是当我这样做时,我会尝试正确设置级联更新/删除以使管理更容易。我了解级联是如何工作的,但我永远不记得哪个表是哪个表。
例如,如果我有两个表 -Parent
并且- 在该引用和 hasChild
上有一个外键,哪些记录会触发级联,哪些记录会被级联删除?我的第一个猜测是删除记录时会删除记录,因为记录依赖于记录,但这是模棱两可的;它可能意味着删除记录时删除记录,也可能意味着删除记录时删除记录。那么它是哪一个?Child
Parent
ON DELETE CASCADE
Child
Parent
Child
Parent
ON DELETE
Parent
Child
Child
Parent
我希望语法是ON PARENT DELETE, CASCADE
,ON FOREIGN DELETE, CASCADE
或类似的东西来消除歧义。有没有人有任何助记符来记住这一点?
如果你喜欢
Parent
andChild
术语并且你觉得它们很容易被记住,你可能会喜欢ON DELETE CASCADE
to的翻译Leave No Orphans!
这意味着当
Parent
删除(杀死)行时,表中不应存在孤立行Child
。父行的所有子行也被杀死(删除)。如果这些孩子中的任何一个有孙子(通过另一个外键在另一个表中)并且有ON DELETE CASCADE
定义,那么这些也应该被杀死(以及所有后代,只要定义了级联效应。)FOREIGN KEY
约束本身也可以描述为(首先Allow No Orphans!
)。Child
如果没有Parent
(父表中的一行),则不应在子表中允许(写入) No 。为了保持一致性,
ON DELETE RESTRICT
可以将其翻译为(不那么激进)You Can't Kill Parents!
只有无子行可以被杀死(删除。)ON DELETE CASCADE 是外键声明中的可选子句。所以它与外键声明一起使用。(意思是,在“孩子”表中。)
解释外键声明的一种方法是,“该列的所有有效值都来自 'that_table' 中的 'that_column'。” 当您删除“子”表中的一行时,没有人关心。它不会影响数据完整性。
当您从“父”表(从“that_table”)中删除一行时,您会从“子”表的可能值中删除一个有效值。为了保持数据完整性,您必须对“子”表做一些事情。级联删除是您可以做的一件事。
章节和诗句,来自PostgreSQL 文档。
SQL:2011 规范
有五个选项
ON DELETE
可以ON UPDATE
适用于FOREIGN KEY
. 这些被称为<referential actions>
,直接来自 SQL:2011 规范外键建立依赖关系。这
<referential action>
决定了关系解散时会发生什么。例子/隐喻/解释
对于这个例子,我们将接受社会和经济的共同模型:每个人
business
都是一家公司,bourgeoisie
通过fatcat_owner
.如果所有
business
的 es 都直接受到bourgeoisie
他们的影响,fatcat_owner
那么在工人革命之后,当你清洗fatcat_owner
s 并拥有一个无阶级的社会时,你会怎么做?你有几个选择,
停止革命。在 SQL 用语中,
RESTRICT
. 有些人认为这是较小的邪恶,但他们通常是错误的。让它继续下去。如果是这样,当革命发生时,SQL 为您提供了四个选项,
SET NULL
——留空。谁知道呢,也许资本主义恢复bourgeoisie
了,寡头们占了上风fatcat_owners
。重要说明,该列必须是NULLABLE
(notNOT NULL
) 否则这永远不会发生。SET DEFAULT
- 也许你有一个DEFAULT
处理这个?ADEFAULT
可以调用一个函数。也许您的架构已经为革命做好了准备。CASCADE
——没有损害控制。如果bourgeoisie
去,那么business
. 如果一个业务必须有一个fatcat_owner
,那么有时丢失数据比在business
表中包含一个非业务更有意义。NO ACTION
-- 这本质上是一种延迟检查的方法,在 MySQL 中它与 没有什么不同RESTRICT
,但在 PostgreSQL 中,你可以做到在这样的系统中,仅在事务提交之前验证约束。这可能会导致革命停止,但您可以在交易中恢复——某种程度的“恢复”。
一个简单的助记符是
ON DELETE of parent CASCADE [by delete] here
这会告诉您哪些删除(父级的删除)被级联,ON DELETE CASCADE语句在哪里(在子级上),以及什么被删除(子级)。
好吧,也许我们可以合理化语法。让我们以 Python 为例:
此行所说的是父级的 on_delete (语句中意外提及),请将删除级联到子级。这就是为什么在子级定义 CASCADE 语句的原因,它标记了那些需要删除的子级
例如,如果您有另一堂课
这个结构将清楚地显示哪些孩子需要被移除(Child),哪些孩子要留下(GrownUpChild),尽管是孤儿
[编辑:鉴于讨论的上下文,特别是在 on_delete=models.CASCADE 等情况下,] 事实上,由于审计和报告原因,以及恢复意外,离开已删除父母的孩子通常是一种理想的行为删除。[当然企业级软件将围绕这种行为构建,并将已删除的记录标记为已删除=1,而不是实际删除它们,并且也不会将它们包含在前端的任何查询中,减去一些专门设计的报告。另外它还有一个从数据库中清除deleted==1记录的功能,这个功能通常由UI管理员来执行,通常避免数据库管理员方面的任何参与。]