Skip to content
Advertisement

How to insert data into table even if trigger fails?

Oracle 11.1

I have custom logging table where I insert data:

CREATE TABLE log_table
(
    message      VARCHAR2(255),
    created_by   VARCHAR2(40) NOT NULL,
    created_at   DATE         NOT NULL,
);

I have a trigger that runs on a specific table which does some checkings. My problem is: when the trigger fails, I want to be able to log some data into the log_table.

Trigger:

CREATE OR REPLACE TRIGGER my_trigger
    FOR INSERT OR UPDATE OF column
    ON my_table
    COMPOUND TRIGGER

BEFORE STATEMENT IS
BEGIN
   // code
END BEFORE STATEMENT;

    BEFORE EACH ROW IS
    BEGIN
        IF (/*condition for failing*/) THEN
            EXECUTE IMMEDIATE 'INSERT INTO mesaj_ama VALUES (:my_message, :my_user, :my_data)'
                USING 'custom error message', SYS.LOGIN_USER, SYSDATE;
            RAISE_APPLICATION_ERROR(-20001, 'some error');
        END IF;
    END BEFORE EACH ROW;
    END my_trigger;
/

The following code doesn’t work. I tried to use EXECUTE IMMEDIATE maybe to force it, but didn’t work. I know that in case of an error, there is automatically a table rollback (which means that the INSERT command is cancelled), but I need a way to do this. Any help?

Advertisement

Answer

Yes, PRAGMA AUTONOMOUS_TRANSACTION seems to be the answer. Here is the working code:

Defined a procedure for logging:

CREATE OR REPLACE PROCEDURE log_error(p_error log_table.message % TYPE) AS
    PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
    INSERT INTO log_table
    VALUES (p_error, SYS.LOGIN_USER, SYSDATE);
    COMMIT;
END;

and the trigger which calls the procedure:

CREATE OR REPLACE TRIGGER my_trigger
    FOR INSERT OR UPDATE OF column
    ON my_table
    COMPOUND TRIGGER

BEFORE STATEMENT IS
BEGIN
   // code
END BEFORE STATEMENT;

    BEFORE EACH ROW IS
    BEGIN
        IF (/*condition for failing*/) THEN

           log_error('custom error message');
           RAISE_APPLICATION_ERROR(-20001, 'custom error message');

        END IF;
    END BEFORE EACH ROW;
    END my_trigger;
/
Advertisement