Oracle   发布时间:2022-05-17  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了删除触发后的Oracle …如何避免变异表(ORA-04091)?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
假设我们有以下表格结构:
documents      dOCMentStatusHistory      status
+---------+   +--------------------+    +----------+
| docID   |   | docStatusHistoryID |    | statusID |
+---------+   +--------------------+    +----------+
| ...     |   | docID              |    | ...      |
+---------+   | statusID           |    +----------+
              | ...                |
              +--------------------+

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

系统性能缓慢但肯定会降低,我建议将上述结构更改为:

documents           dOCMentStatusHistory      status
+--------------+   +--------------------+    +----------+
| docID        |   | docStatusHistoryID |    | statusID |
+--------------+   +--------------------+    +----------+
| currStatusID |   | docID              |    | ...      |
| ...          |   | statusID           |    +----------+
+--------------+   | ...                |
                   +--------------------+

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

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

在这种情况下,我不得不为我的规则打开一个例外以不惜一切代价避免触发器,因为我无法访问遗留应用程序代码.

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

但是,在一个模糊且很少使用的情况下,需要删除最后的状态历史记录,而不是简单地添加新的状态历史记录.所以,我创建了以下触发器:

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.

我明白为什么我收到此错误,即使我将触发器配置为AFTER触发器.

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

我们正在使用oracle 9i.

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

>包含密钥集合的包(在本例中为docID).临时表也可以
>初始化集合的before语句触发器
>行级触发器,使用已更改的每个docID填充集合
>一个after语句触发器,它迭代集合并执行实际的updatE

所以像

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)?全部内容,希望文章能够帮你解决删除触发后的Oracle …如何避免变异表(ORA-04091)?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: