首页 文章

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

提问于
浏览
1

得到一个简短的问题 . 所以我有一个名为PARENT的表和一个名为CHILD的表,假设它们处于父子关系中 . 当删除其他表的数据时,是否可以删除其中一个?

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

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

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

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

编辑:我来到oracle文档中进行复合触发,这是一个有趣的读物 . 如果它成功,我会更新它 .

1 回答

  • 1

    这种级联通常没有意义 . 创建子项时父项必须存在 . 所以它的常识不应该只是因为没有孩子而被删除 .

    如果仅使用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;
    

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

相关问题