In Oracle, when a runtime error occurs in a SQL command, all the updates on the database caused by that single command are rolled back. This is called statement level transaction isolation. For example, if a single UPDATE command successfully updates five rows, but an attempt to update a sixth row results in an exception, the updates to all six rows made by this UPDATE command are rolled back. The effects of prior SQL commands that have not yet been committed or rolled back are pending until a COMMIT or ROLLBACK command is executed.
In PostgreSQL, if an exception occurs while executing a SQL command, all the updates on the database since the start of the transaction are rolled back. In addition, the transaction is left in an aborted state and either a COMMIT or ROLLBACK command must be issued before another transaction can be started.
If edb_stmt_level_tx is set to “true”, then an exception will not automatically roll back prior uncommitted database updates, emulating the Oracle behavior. If edb_stmt_level_tx is set to “false”, then an exception will roll back uncommitted database updates.
Note: Currently in SPL programs, edb_stmt_level_tx always operates as if it were set to “false”. An exception in an SPL program will always roll back uncommitted updates that have occurred within the scope of the block in which the exception is finally caught. Support of edb_stmt_level_tx = “true” in SPL programs will be provided in a future release.
Note: Use edb_stmt_level_tx set to “true” only when absolutely necessary as this may cause a negative performance impact.
The following example run in PSQL shows that when edb_stmt_level_tx is “false”, the abort of the second INSERT command also rolls back the first INSERT command. Note that in PSQL, the command \set AUTOCOMMIT off must be issued, otherwise every statement commits automatically defeating the purpose of this demonstration of the effect of edb_stmt_level_tx.
\set AUTOCOMMIT off SET edb_stmt_level_tx TO off; INSERT INTO emp (empno,ename,deptno) VALUES (9001, 'JONES', 40); INSERT INTO emp (empno,ename,deptno) VALUES (9002, 'JONES', 00); ERROR: insert or update on table "emp" violates foreign key constraint "emp_ref_dept_fk" DETAIL: Key (deptno)=(0) is not present in table "dept". COMMIT; SELECT empno, ename, deptno FROM emp WHERE empno > 9000; empno | ename | deptno -------+-------+-------- (0 rows)
In the following example, with edb_stmt_level_tx set to “true”, the first INSERT command has not been rolled back after the error on the second INSERT command. At this point, the first INSERT command can either be committed or rolled back.
\set AUTOCOMMIT off SET edb_stmt_level_tx TO on; INSERT INTO emp (empno,ename,deptno) VALUES (9001, 'JONES', 40); INSERT INTO emp (empno,ename,deptno) VALUES (9002, 'JONES', 00); ERROR: insert or update on table "emp" violates foreign key constraint "emp_ref_dept_fk" DETAIL: Key (deptno)=(0) is not present in table "dept". SELECT empno, ename, deptno FROM emp WHERE empno > 9000; empno | ename | deptno -------+-------+-------- 9001 | JONES | 40 (1 row) COMMIT;
A ROLLBACK command could have been issued instead of the COMMIT command in which case the insert of employee number 9001 would have been rolled back as well.