Oracle:删除子项时删除父表(双向级联删除)

时间:2015-09-19 00:47:58

标签: database oracle parent-child cascading-deletes

快速提问。 所以我有一个名为PARENT的表和一个名为CHILD的表,假设它们处于父子关系中。删除其他表的数据时是否可以删除其中一个?

我最初的尝试是使用级联删除来删除CHILD记录删除PARENT记录时。 同时我在删除CHILD的记录时使用触发器删除PARENT记录。(条件是在CHILD上删除,触发后)

结果是ORA-04091:表格是变异的。 它造成了一种僵局。

父表已删除 - >级联删除子 - >触发器触发删除父级, 此时,PARENT中已删除的记录未提交,因此我们处于不稳定状态。

是否有可能以这种方式关联父和子表的记录,如果一个被删除,另一个也被杀死了?我们假设这个CHILD表是唯一的子节点,CHILD中具有外键的列与PARENT中的引用列具有1对1的关系。

编辑:我来过oracle文档进行复合触发,这是一个有趣的读物。如果有效,我会更新它。

1 个答案:

答案 0 :(得分:2)

这种级联通常没有意义。 创建子项时父项必须存在。所以常识不应仅仅因为没有孩子而删除父母。

如果您只使用1对1的关系,则只需要更改程序逻辑,以便在需要删除子项时仅删除父记录。

然而,如果你真的需要这个东西。我称之为LONELY_PARENT_CLEANUP程序。现在,当我们有名称和意义时,我们只需要执行它。 因为我们无法从触发器(变异表!)运行它,所以我们应该进行清理工作。我们可以通过触发器或某些时间表启动此作业。在清除父母之前可能会有轻微的延迟。

假设我们的TEST_PARENT表包含列(id)TEST_CHILD表,列(id, parent_id)。我们用DELETE CASCADE创建了FK 创建删除父项的过程。我建议我们尽快删除父母。

CREATE OR REPLACE PROCEDURE DELETE_LONELY_PARENT (p_id IN NUMBER) AS 
BEGIN
  DELETE FROM test_parent WHERE id = p_id;
  COMMIT;
END DELETE_LONELY_PARENT;

现在我们需要TEST_CHILD表上的triger:

CREATE OR REPLACE TRIGGER DELETE#PARENT#TRG 
BEFORE DELETE ON TEST_CHILD FOR EACH ROW
DECLARE
  jobId NUMBER;
BEGIN
  dbms_job.submit(
    job => jobId, 
    what => 'BEGIN DELETE_LONELY_PARENT('|| :old.parent_id ||'); END;'
  );
END;

现在,当您删除子记录时,特殊作业将开始删除父记录。由于其不同的交易,不再存在变异表问题。

相关问题