【问题标题】:How to have Delete Cascade on both column that refer the same table?如何在引用同一个表的两个列上删除级联?
【发布时间】:2021-05-03 15:06:30
【问题描述】:

我有一个项目表:

ID NAME
1 GrandParent
2 Parent1
3 Parent2
4 Child1

还有一个 ItemRelations 表:

ParentItemId ChildItemId
1 2
1 3
2 4

我正在尝试在 itemTable 的 ParentItemId 和 ChildItemId 上使用删除级联的外键, 当我删除 GrandParent 时,我想保持 Parent1 和 Child1 之间的关系 但 SQL 不允许我这样做:

'- 无法创建关系“FK_BlockRelations_Child”。 在表上引入 FOREIGN KEY 约束“FK_BlockRelations_Child” “BlockRelations”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN 关键约束。无法创建约束或索引。见上 错误。'

【问题讨论】:

  • 您使用的是哪个 dbms?
  • 我正在使用 SQL Server
  • 您是否尝试将 parentItemId 和 childItemId 都指向父表中的 ID 列。你有没有在此处发布的名称为 BlockRelations 的任何其他表。问题似乎与该表有关

标签: sql sql-server database cascading-deletes


【解决方案1】:

父母/祖父母的概念似乎没有必要,因为如果您正在进行递归的事情,并且在任何时候,一个项目可以是孩子、祖父母或父母。

在任何情况下,您都试图向数据库提供相互冲突的指令:

一方面,您说“我正在尝试在 ParentItemId 和 ChildItemId 上使用删除级联到 itemTable 的外键” 然后在下一句“当我删除 GrandParent 时,我想保留 Parent1 和 Child1 之间的关系,但 SQL 不允许我”

当您决定创建级联删除时,这意味着您正在做两件事:

  1. 强制外键约束 - 对孤儿零容忍
  2. 根据这些外键约束,您正在执行一项操作,即在删除项目时删除与项目相关的项目关系中的所有内容

一旦您强制执行 (1),那么您将不能在未首先存在于项目中的情况下将项目添加到项目关系中。

如果您随后根据强制执行 #1 执行级联删除操作,那么您需要选择在哪个字段上使用它。除非两者都链接到不同的表,或者一个是级联的,而另一个没有操作,否则不能两者兼而有之。

另一方面,如果您想删除祖父母并将项目保留在项目关系中,那么您的意思是您不再想要 #1 - 没有外来约束强制执行和对孤儿的容忍。

一旦你决定了你想要的,正确的方法应该是明确的。

如果您的删除级联和外键强制执行是有条件的并且基于父级的值,您可能需要完全放弃外键约束强制并考虑插入和删除触发器。

【讨论】:

  • 说我想删除 Parent1。想要的最终结果是删除 parent1 是父项或子项的所有 itemRelations。我必须在 ParentItemId 上执行 1 次删除级联,并在它是孩子时执行删除触发器?
  • 理想情况下,您想要的是 ItemRelations 上的自引用外键,当它由级联删除或项目的删除触发器触发时级联删除自身,但 DBMS 不允许这样做,所以你实际上需要的是 ItemRelations 上的删除触发器,然后在检测到时,使用递归 CTE 查找所有相关 id 并将它们全部删除。
猜你喜欢
  • 1970-01-01
  • 2012-01-07
  • 2011-06-27
  • 2017-08-10
  • 1970-01-01
  • 2023-02-23
  • 1970-01-01
  • 2020-06-14
  • 2019-07-11
相关资源
最近更新 更多