COMMIT in Functions/Triggers.
+++++++++++++++++++
It Triggers/functions may be led to bulk associated transactions. This may lead to transaction atomicity failure.
Please find the below test case from Oracle.
Step 1:
---------
SQL> CREATE TABLE COMMIT_TRIG_TEST_TABLE1(T INT);
Table created.
SQL> CREATE TABLE COMMIT_TRIG_TEST_TABLE2(T INT,CHECK (T NOT IN(0)));
Table created.
Step 2:
---------
CREATE OR REPLACE FUNCTION INSERT_DATA(NUM IN NUMBER)
RETURN VARCHAR2 IS
BEGIN
EXECUTE IMMEDIATE 'INSERT INTO COMMIT_TRIG_TEST_TABLE1 VALUES('||NUM||')';
RETURN 'INSERT OK';
END;
Step 3:
---------
CREATE OR REPLACE TRIGGER COMMIT_TRIG
BEFORE INSERT ON COMMIT_TRIG_TEST_TABLE1
FOR EACH ROW
DECLARE
BEGIN
INSERT INTO COMMIT_TRIG_TEST_TABLE2 VALUES(:NEW.T);
END;
Step 4:
--------
However, we know that if the function having dml operations, then we can't make that function as a part of SQL statement. So, please use the below method for inserting
the data.
SQL> VAR V VARCHAR2(10);
SQL> EXEC :V :=INSERT_DATA(10);
PL/SQL procedure successfully completed.
SQL> PRINT V;
V
------------------
INSERT OK
Please observer this statement in INSERT_DATA function .
This insert statement is associated with two transactions.
1. By itself.
2.INSERT INTO COMMIT_TRIG_TEST_TABLE2 VALUES:
InTrigger Body Asper Atomocity(ACID), whether the transaction must Commit/Rollback.
+INSERT ON TABLE1 (Success)+ }
==> TRANSACTION is sucess.
+INSERT ON TABLE2 (Success)+ }
SQL> SELECT * FROM COMMIT_TRIG_TEST_TABLE1;
T
----------
10
SQL> SELECT * FROM COMMIT_TRIG_TEST_TABLE2;
T
----------
10
That's why this EXEC :V :=INSERT_DATA(10) is sucessfull.
Step 5
--------
SQL> DELETE FROM COMMIT_TRIG_TEST_TABLE1;
SQL> DELETE FROM COMMIT_TRIG_TEST_TABLE2;
SQL> exec :v :=insert_data(0);
BEGIN :v :=insert_data(0); END;
*
ERROR at line 1:
ORA-02290: check constraint (SCOTT.SYS_C009672) violated
ORA-06512: at "SCOTT.COMMIT_TRIG", line 3
ORA-04088: error during execution of trigger 'SCOTT.COMMIT_TRIG'
ORA-06512: at "SCOTT.INSERT_DATA", line 4
ORA-06512: at line 1
Here the transactions are as below
+INSERT ON TABLE1 (Success)+}
==> TRANSACTION is failure.
+INSERT ON TABLE2 (Failure)+}
As per Automocity rule, whether the transaction must be sucess/fail. However, here the transaction is having both.
That's why the total transaction is rolled back. So, INSERT ON TABLE1 also rolled back here.
SQL> SELECT * FROM COMMIT_TRIG_TEST_TABLE1;
no rows selected
SQL> SELECT * FROM COMMIT_TRIG_TEST_TABLE2;
no rows selected
Even though if you have autonomous_transactions, those must and should statisfy this automoctiy.
Now, how to insert element '0' in first table.
Step 6
--------
CREATE OR REPLACE FUNCTION INSERT_DATA(NUM IN NUMBER)
RETURN VARCHAR2 IS
pragma autonomous_transaction;
BEGIN
INSERT INTO COMMIT_TRIG_TEST_TABLE1 VALUES(NUM);
COMMIT;
RETURN 'INSERT OK';
END;
Need to make the trigger always commits.Even though it fails, it needs to commit for satisfying the automocity.
CREATE OR REPLACE TRIGGER COMMIT_TRIG
BEFORE INSERT ON COMMIT_TRIG_TEST_TABLE1
FOR EACH ROW
DECLARE
pragma autonomous_transaction;
BEGIN
INSERT INTO COMMIT_TRIG_TEST_TABLE2 VALUES(:NEW.T);
commit;
exception when others then
COMMIT;
END;
SQL> select insert_data(0) from dual;
INSERT_DATA(0)
--------------------------------------------------------------------------------
INSERT OK
SQL> select * from commit_trig_test_table1;
T
----------
0
SQL> select * from commit_trig_test_table2;
no rows selected
--Dinesh
+++++++++++++++++++
It Triggers/functions may be led to bulk associated transactions. This may lead to transaction atomicity failure.
Please find the below test case from Oracle.
Step 1:
---------
SQL> CREATE TABLE COMMIT_TRIG_TEST_TABLE1(T INT);
Table created.
SQL> CREATE TABLE COMMIT_TRIG_TEST_TABLE2(T INT,CHECK (T NOT IN(0)));
Table created.
Step 2:
---------
CREATE OR REPLACE FUNCTION INSERT_DATA(NUM IN NUMBER)
RETURN VARCHAR2 IS
BEGIN
EXECUTE IMMEDIATE 'INSERT INTO COMMIT_TRIG_TEST_TABLE1 VALUES('||NUM||')';
RETURN 'INSERT OK';
END;
Step 3:
---------
CREATE OR REPLACE TRIGGER COMMIT_TRIG
BEFORE INSERT ON COMMIT_TRIG_TEST_TABLE1
FOR EACH ROW
DECLARE
BEGIN
INSERT INTO COMMIT_TRIG_TEST_TABLE2 VALUES(:NEW.T);
END;
Step 4:
--------
However, we know that if the function having dml operations, then we can't make that function as a part of SQL statement. So, please use the below method for inserting
the data.
SQL> VAR V VARCHAR2(10);
SQL> EXEC :V :=INSERT_DATA(10);
PL/SQL procedure successfully completed.
SQL> PRINT V;
V
------------------
INSERT OK
Please observer this statement in INSERT_DATA function .
This insert statement is associated with two transactions.
1. By itself.
2.INSERT INTO COMMIT_TRIG_TEST_TABLE2 VALUES:
InTrigger Body Asper Atomocity(ACID), whether the transaction must Commit/Rollback.
+INSERT ON TABLE1 (Success)+ }
==> TRANSACTION is sucess.
+INSERT ON TABLE2 (Success)+ }
SQL> SELECT * FROM COMMIT_TRIG_TEST_TABLE1;
T
----------
10
SQL> SELECT * FROM COMMIT_TRIG_TEST_TABLE2;
T
----------
10
That's why this EXEC :V :=INSERT_DATA(10) is sucessfull.
Step 5
--------
SQL> DELETE FROM COMMIT_TRIG_TEST_TABLE1;
SQL> DELETE FROM COMMIT_TRIG_TEST_TABLE2;
SQL> exec :v :=insert_data(0);
BEGIN :v :=insert_data(0); END;
*
ERROR at line 1:
ORA-02290: check constraint (SCOTT.SYS_C009672) violated
ORA-06512: at "SCOTT.COMMIT_TRIG", line 3
ORA-04088: error during execution of trigger 'SCOTT.COMMIT_TRIG'
ORA-06512: at "SCOTT.INSERT_DATA", line 4
ORA-06512: at line 1
Here the transactions are as below
+INSERT ON TABLE1 (Success)+}
==> TRANSACTION is failure.
+INSERT ON TABLE2 (Failure)+}
As per Automocity rule, whether the transaction must be sucess/fail. However, here the transaction is having both.
That's why the total transaction is rolled back. So, INSERT ON TABLE1 also rolled back here.
SQL> SELECT * FROM COMMIT_TRIG_TEST_TABLE1;
no rows selected
SQL> SELECT * FROM COMMIT_TRIG_TEST_TABLE2;
no rows selected
Even though if you have autonomous_transactions, those must and should statisfy this automoctiy.
Now, how to insert element '0' in first table.
Step 6
--------
CREATE OR REPLACE FUNCTION INSERT_DATA(NUM IN NUMBER)
RETURN VARCHAR2 IS
pragma autonomous_transaction;
BEGIN
INSERT INTO COMMIT_TRIG_TEST_TABLE1 VALUES(NUM);
COMMIT;
RETURN 'INSERT OK';
END;
Need to make the trigger always commits.Even though it fails, it needs to commit for satisfying the automocity.
CREATE OR REPLACE TRIGGER COMMIT_TRIG
BEFORE INSERT ON COMMIT_TRIG_TEST_TABLE1
FOR EACH ROW
DECLARE
pragma autonomous_transaction;
BEGIN
INSERT INTO COMMIT_TRIG_TEST_TABLE2 VALUES(:NEW.T);
commit;
exception when others then
COMMIT;
END;
SQL> select insert_data(0) from dual;
INSERT_DATA(0)
--------------------------------------------------------------------------------
INSERT OK
SQL> select * from commit_trig_test_table1;
T
----------
0
SQL> select * from commit_trig_test_table2;
no rows selected
--Dinesh
Comments
Post a Comment