Oracle After Delete Trigger ... How to Avoid Mutating Table (ORA-04091)?

Say we have the following table structures:

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

This may be obvious, but it is worth mentioning that the current status of the document is the last entered status history.

The system was slowly but surely getting worse in performance, and I suggested changing the structure above:

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

Thus, we will have the current status of the document, where it should be.

Since the way to create obsolete applications, I could not change the code for obsolete applications to update the current status in the document table.

In this case, I had to open an exception to my rule to avoid triggers at all costs, simply because I do not have access to outdated application code.

, , , .

. , :

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.

+5
2

  • (.. docId ). .
  • , docId
  • 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;
+9

+1

All Articles