ROLLBACK 命令撤消當前事務(wù)期間執(zhí)行的所有數(shù)據(jù)庫更新,并結(jié)束當前事務(wù)。
ROLLBACK [ WORK ];
ROLLBACK 命令可在匿名塊、存儲過程或函數(shù)中使用。在 SPL 程序內(nèi),它可出現(xiàn)在可執(zhí)行部分和/或異常部分中。
在以下示例中,異常部分包含 ROLLBACK 命令。即使前兩個 INSERT 命令成功執(zhí)行,第三個命令也會因匿名塊中所有 INSERT 命令的回滾而導致異常。
\set AUTOCOMMIT off
SET polar_comp_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。首先,創(chuàng)建了以下存儲過程,其中插入了一個新員工。
\set AUTOCOMMIT off
SET polar_comp_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;
請注意,此存儲過程沒有異常部分,因此可能發(fā)生的任何錯誤都會向上傳播到調(diào)用程序。
將運行以下匿名塊。請注意,在對 emp_insert 存儲過程和異常部分中的 ROLLBACK 命令進行所有調(diào)用后使用了 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)
現(xiàn)在,執(zhí)行以下匿名塊:
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 命令產(chǎn)生以下輸出:
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 存儲過程中執(zhí)行 COMMIT 或 ROLLBACK 將會引發(fā)錯誤。