'How to get the main ID of updated row and use it before DML in trigger

I'm blocked with the development of an Oracle trigger (11g). The goal of the trigger is to store some data in an audit trail table. One of the fields that is populated in this table is an XML block generated by a function in a package. This function has 1 argument: The ID of the row to be updated / deleted.

So I first wrote this trigger:

CREATE OR REPLACE TRIGGER TRG_TEMPLATE_FORMAT
BEFORE UPDATE OR DELETE
ON TEMPLATE_FORMAT
FOR EACH ROW

DECLARE
    v_TEMPLATE_XML          CLOB;  
    v_TEMPLATE_NAME         VARCHAR2(128);
    v_TEMPLATE_FULL_NAME    VARCHAR2(128);
BEGIN
    IF UPDATING THEN
        SELECT TEMPLATE_NAME INTO v_TEMPLATE_NAME FROM TEMPLATES WHERE TEMPLATE_ID =: OLD.TEMPLATE_ID;
        SELECT TEMPLATE_FULL_NAME INTO v_TEMPLATE_FULL_NAME FROM TEMPLATES WHERE TEMPLATE_ID = :OLD.TEMPLATE_ID;
        v_TEMPLATE_XML := PKG_TEMPLATE_MANAGEMENT.GET_TEMPLATE_XML(:OLD.TEMPLATE_ID);   
        INSERT INTO TEMPLATES_BACK(
            TEMPLATE_ID,
            TEMPLATE_FULL_NAME,
            TEMPLATE_NAME,
            EVENT_TYPE,
            EVENT_TIMESTAMP,
            OLD_XML_TEMPLATE_SOURCE        
        )
        VALUES(
            :OLD.TEMPLATE_ID,
            v_TEMPLATE_FULL_NAME,
            v_TEMPLATE_NAME,
            'UPDATE ON TEMPLATE_FORMAT',
            SYSDATE,
            v_TEMPLATE_XML
        );
    ELSIF DELETING THEN
        SELECT TEMPLATE_NAME INTO v_TEMPLATE_NAME FROM TEMPLATES WHERE TEMPLATE_ID = :OLD.TEMPLATE_ID;
        SELECT TEMPLATE_FULL_NAME INTO v_TEMPLATE_FULL_NAME FROM TEMPLATES WHERE TEMPLATE_ID = :OLD.TEMPLATE_ID;
        v_TEMPLATE_XML := PKG_TEMPLATE_MANAGEMENT.GET_TEMPLATE_XML(:OLD.TEMPLATE_ID);
        INSERT INTO TEMPLATES_BACK(
            TEMPLATE_ID,
            TEMPLATE_FULL_NAME,
            TEMPLATE_NAME,
            EVENT_TYPE,
            EVENT_TIMESTAMP,
            OLD_XML_TEMPLATE_SOURCE        
        )
        VALUES(
            :OLD.TEMPLATE_ID,
            v_TEMPLATE_FULL_NAME,
            v_TEMPLATE_NAME,
            'DELETE FROM TEMPLATE_FORMAT',
            SYSDATE,
            v_TEMPLATE_XML
        );
    END IF;
END;
/

As the TEMPLATE_FORMAT table is used in the GET_TEMPLATE_XML() Function, of course, I get the old "good" "Table is mutating" error...

I thought about using a compound trigger after searching a bit, and call my function in the BEFORE STATEMENT block. Problem is that the :OLD / :NEW binds, can't be used in that block

Final Goal of this XML is to capture the values of several records, in this XML before any modification, so it can be easily rolled back.

Is there another way I could have missed to handle this case ?

Thanks in advance



Solution 1:[1]

Solved by adding pragma autonomous_transaction in called function (PKG_TEMPLATE_MANAGEMENT.GET_TEMPLATE_XML).

Thanks again @ekochergin

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1