gpt4 book ai didi

Oracle 删除触发器后...如何避免变异表 (ORA-04091)?

转载 作者:行者123 更新时间:2023-12-04 17:27:34 24 4
gpt4 key购买 nike

假设我们有以下表结构:

documents      docmentStatusHistory      status
+---------+ +--------------------+ +----------+
| docId | | docStatusHistoryId | | statusId |
+---------+ +--------------------+ +----------+
| ... | | docId | | ... |
+---------+ | statusId | +----------+
| ... |
+--------------------+

可能很明显,但值得一提的是,文档的当前状态是最后输入的状态历史记录。

该系统的性能缓慢但肯定会下降,我建议将上述结构更改为:
documents           docmentStatusHistory      status
+--------------+ +--------------------+ +----------+
| docId | | docStatusHistoryId | | statusId |
+--------------+ +--------------------+ +----------+
| currStatusId | | docId | | ... |
| ... | | statusId | +----------+
+--------------+ | ... |
+--------------------+

通过这种方式,我们可以将文档的当前状态放在应有的位置。

由于遗留应用程序的构建方式,我无法更改遗留应用程序的代码以更新文档表上的当前状态。

在这种情况下,我不得不为我的规则打开一个异常(exception),以不惜一切代价避免触发器,仅仅是因为我无法访问遗留应用程序代码。

我创建了一个触发器,每次将新状态添加到状态历史记录时都会更新文档的当前状态,它的作用就像一个魅力。

但是,在一个晦涩且很少使用的情况下,需要 删除 最后一个状态历史,而不是简单地添加一个新的。所以,我创建了以下触发器:
create or replace trigger trgD_History
after delete on documentStatusHistory
for each row
currentStatusId number;
begin

select statusId
into currentStatusId
from documentStatusHistory
where docStatusHistoryId = (select max(docStatusHistoryId)
from documentStatusHistory
where docId = :old.docId);

update documentos
set currStatusId = currentStatusId
where docId = :old.docId;
end;

这就是我得到臭名昭著的错误 ORA-04091 的地方.

我明白为什么我会收到这个错误,即使我将触发器配置为 扳机。

问题是我看不到解决此错误的方法。我已经在网上搜索了一段时间,到目前为止找不到任何有用的东西。

随着时间的推移,我们正在使用 Oracle 9i。

最佳答案

变异表错误的标准解决方法是创建

  • 带有一组键的包(即本例中的 docId)。临时表也可以使用
  • 初始化集合的 before 语句触发器
  • 一个行级触发器,用每个改变的 docId 填充集合
  • 迭代集合并执行实际更新的 after 语句触发器

  • 所以像
    CREATE OR REPLACE PACKAGE pkg_document_status
    AS
    TYPE typ_changed_docids IS TABLE OF documentos.docId%type;
    changed_docids typ_changed_docids := new typ_changed_docids ();

    <<other methods>>
    END;

    CREATE OR REPLACE TRIGGER trg_init_collection
    BEFORE DELETE ON documentStatusHistory
    BEGIN
    pkg_document_status.changed_docids.delete();
    END;

    CREATE OR REPLACE TRIGGER trg_populate_collection
    BEFORE DELETE ON documentStatusHistory
    FOR EACH ROW
    BEGIN
    pkg_document_status.changed_docids.extend();
    pkg_document_status.changed_docids( pkg_document_status.changed_docids.count() ) := :old.docId;
    END;

    CREATE OR REPLACE TRIGGER trg_use_collection
    AFTER DELETE ON documentStatusHistory
    BEGIN
    FOR i IN 1 .. pkg_document_status.changed_docids.count()
    LOOP
    <<fix the current status for pkg_document_status.changed_docids(i) >>
    END LOOP;
    pkg_document_status.changed_docids.delete();
    END;

    关于Oracle 删除触发器后...如何避免变异表 (ORA-04091)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5805986/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com