Oracle では、SQL 文でランタイムエラーが発生すると、その単一の文によって引き起こされたデータベース上のすべての更新がロールバックされます。 これは、文レベルのトランザクション分離と呼ばれます。 たとえば、単一の UPDATE 文が 5 つの行を更新し、6 番目の行を更新しようとした際にエラーが発生した場合、この UPDATE 文によって行われた 6 つすべての行への更新はロールバックされます。 まだコミットまたはロールバックされていない以前の SQL 文の影響は、COMMIT または ROLLBACK 文が実行されるまで保留されます。
PostgreSQL では、SQL 文の実行中にエラーが発生した場合、トランザクション開始以降データベース上のすべての更新がロールバックされます。 さらに、トランザクションが終了状態のままで、別のトランザクションを開始する前に COMMIT または ROLLBACK 文を実行する必要があります。
edb_stmt_level_tx が TRUE に設定されている場合、Oracle の動作と同様に、コミットされていないデータベースの更新がエラーによって自動的にロールバックされることはありません。 edb_stmt_level_tx が FALSE に設定されている場合、エラーにより、コミットされていないデータベースの更新がロールバックされます。
PSQL で実行されている次の例に示すように、edb_stmt_level_tx が FALSE に設定されている場合、2 番目の INSERT 文が終了した後も、最初の INSERT 文はロールバックされたままです。 PSQL では、\set AUTOCOMMIT off 文を使用する必要があります。 使用していない場合、すべての文が自動的にコミットされます。 これは、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)
次の例では、edb_stmt_level_tx が TRUE に設定されています。 2 番目の INSERT 文でエラーが発生した以降、最初の INSERT 文はロールバックされていません。 この時点で、最初の INSERT 文をコミットまたはロールバックすることができます。
\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;
COMMIT 文の代わりに ROLLBACK 文を実行することもできます。 この場合、従業員番号 9001 の挿入もロールバックされます。