ROLLBACK¶
ROLLBACK コマンドは、現在のトランザクション中に行われたすべてのデータベース更新を取り消し、現在のトランザクションを終了します。
ROLLBACK [ WORK ];
ROLLBACK コマンドは、匿名ブロック、ストアドプロシージャ、または関数内で使用できます。SPLプログラム内では、実行可能セクションおよび/または例外セクションに表示される場合があります。
次の例では、例外セクションに ROLLBACK コマンドが含まれています。最初の2つの INSERT コマンドは正常に実行されますが、3番目のコマンドでは例外が発生し、匿名ブロック内のすべての INSERT コマンドがロールバックされます。
\set AUTOCOMMIT off
SET edb_stmt_level_tx TO on;
BEGIN
INSERT INTO dept VALUES (50, 'FINANCE', 'DALLAS');
INSERT INTO dept VALUES (60, 'MARKETING', 'CHICAGO');
INSERT INTO dept VALUES (70, 'HUMAN RESOURCES', 'CHICAGO');
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
DBMS_OUTPUT.PUT_LINE('SQLERRM: ' || SQLERRM);
DBMS_OUTPUT.PUT_LINE('SQLCODE: ' || SQLCODE);
END;
SQLERRM: value too long for type character varying(14)
SQLCODE: 22001
SELECT * FROM dept;
deptno | dname | loc
--------+------------+----------
10 | ACCOUNTING | NEW YORK
20 | RESEARCH | DALLAS
30 | SALES | CHICAGO
40 | OPERATIONS | BOSTON
(4 rows)
以下は、 COMMIT と ROLLBACK の両方を使用したより複雑な例です。最初に、新しい従業員を挿入する次のストアドプロシージャが作成されます。
\set AUTOCOMMIT off
SET edb_stmt_level_tx TO on;
CREATE OR REPLACE PROCEDURE emp_insert (
p_empno IN emp.empno%TYPE,
p_ename IN emp.ename%TYPE,
p_job IN emp.job%TYPE,
p_mgr IN emp.mgr%TYPE,
p_hiredate IN emp.hiredate%TYPE,
p_sal IN emp.sal%TYPE,
p_comm IN emp.comm%TYPE,
p_deptno IN emp.deptno%TYPE
)
IS
BEGIN
INSERT INTO emp VALUES (
p_empno,
p_ename,
p_job,
p_mgr,
p_hiredate,
p_sal,
p_comm,
p_deptno);
DBMS_OUTPUT.PUT_LINE('Added employee...');
DBMS_OUTPUT.PUT_LINE('Employee # : ' || p_empno);
DBMS_OUTPUT.PUT_LINE('Name : ' || p_ename);
DBMS_OUTPUT.PUT_LINE('Job : ' || p_job);
DBMS_OUTPUT.PUT_LINE('Manager : ' || p_mgr);
DBMS_OUTPUT.PUT_LINE('Hire Date : ' || p_hiredate);
DBMS_OUTPUT.PUT_LINE('Salary : ' || p_sal);
DBMS_OUTPUT.PUT_LINE('Commission : ' || p_comm);
DBMS_OUTPUT.PUT_LINE('Dept # : ' || p_deptno);
DBMS_OUTPUT.PUT_LINE('----------------------');
END;
このプロシージャには例外セクションがないため、発生する可能性のあるエラーは呼び出し元プログラムまで伝播されることに注意してください。
次の匿名ブロックが実行されます。例外セクションの emp_insert プロシージャと ROLLBACK コマンドへのすべての呼び出しの後、 COMMIT コマンドの使用に注意してください。
BEGIN
emp_insert(9601,'FARRELL','ANALYST',7902,'03-MAR-08',5000,NULL,40);
emp_insert(9602,'TYLER','ANALYST',7900,'25-JAN-08',4800,NULL,40);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('SQLERRM: ' || SQLERRM);
DBMS_OUTPUT.PUT_LINE('An error occurred - roll back inserts');
ROLLBACK;
END;
Added employee...
Employee # : 9601
Name : FARRELL
Job : ANALYST
Manager : 7902
Hire Date : 03-MAR-08 00:00:00
Salary : 5000
Commission :
Dept # : 40
----------------------
Added employee...
Employee # : 9602
Name : TYLER
Job : ANALYST
Manager : 7900
Hire Date : 25-JAN-08 00:00:00
Salary : 4800
Commission :
Dept # : 40
----------------------
次の SELECT コマンドは、従業員FarrellとTylerが正常に追加されたことを示しています。
SELECT * FROM emp WHERE empno > 9600;
empno | ename | job | mgr | hiredate | sal | comm | deptno
------+--------+--------+-----+--------------------+---------+------+--------
9601| FARRELL| ANALYST|7902 | 03-MAR-08 00:00:00 | 5000.00 | | 40
9602| TYLER | ANALYST|7900 | 25-JAN-08 00:00:00 | 4800.00 | | 40
(2 rows)
ここで、次の匿名ブロックを実行します。
BEGIN
emp_insert(9603,'HARRISON','SALESMAN',7902,'13-DEC-07',5000,3000,20);
emp_insert(9604,'JARVIS','SALESMAN',7902,'05-MAY-08',4800,4100,11);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('SQLERRM: ' || SQLERRM);
DBMS_OUTPUT.PUT_LINE('An error occurred - roll back inserts');
ROLLBACK;
END;
Added employee...
Employee # : 9603
Name : HARRISON
Job : SALESMAN
Manager : 7902
Hire Date : 13-DEC-07 00:00:00
Salary : 5000
Commission : 3000
Dept # : 20
----------------------
SQLERRM: insert or update on table "emp" violates foreign key constraint
"emp_ref_dept_fk"
An error occurred - roll back inserts
テーブルに対して SELECT コマンドを実行すると、次の結果が得られます。
SELECT * FROM emp WHERE empno > 9600;
empno | ename | job | mgr | hiredate | sal | comm | deptno
------+--------+--------+-----+--------------------+---------+------+--------
9601| FARRELL| ANALYST|7902 | 03-MAR-08 00:00:00 | 5000.00 | | 40
9602| TYLER | ANALYST|7900 | 25-JAN-08 00:00:00 | 4800.00 | | 40
(2 rows)
例外セクションの ROLLBACK コマンドは、従業員Harrisonの挿入を正常に取り消します。また、従業員FarrellとTylerは、最初の匿名ブロックの COMMIT コマンドによって挿入が永続化されたため、まだテーブルにいることに注意してください。
注釈
ランタイムスタックにOracleスタイルのSPLプロシージャがある場合、plpgsqlプロシージャで COMMIT または ROLLBACK を実行するとエラーがスローされます。