ROLLBACK¶
</ div>
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の挿入を正常に取り消します。また、最初の匿名ブロックでCOMMITコマンドによって挿入が永続化されたため、従業員FarrellとTylerはまだテーブルにいることにノートしてください。
!!! Note *
ランタイムスタックにOracleスタイルのSPLプロシージャがある場合、plpgsqlプロシージャでCOMMITまたはROLLBACKを実行するとエラーがスローされます。