Oracle。如何实现嵌套事务
问题描述:
我被这样一个接一个执行脚本中的几个SQL文件:Oracle。如何实现嵌套事务
@script-A.sql;
@script-B.sql;
@script-C.sql;
...
每个脚本文件做一些有用的,看起来像这样:
DECLARE
...
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE SOME-TABLE';
-- lots of inserts into SOME_TABLE
COMMIT;
END;
/
我必须在一个大事务中包装sql文件执行。如果执行任何sql文件失败,则应该回滚所有先前的sql文件更改。
我该怎么做?
P.S
作为@Mat注意到DDL变化(截断表)不能rollbacked。如果需要的话,我可以自由地重构这行代码。
答
首先,您应该消除DDL并从代码中提交。然后添加一个在所有脚本执行后提交行。然后最后你需要的是设置SQL * Plus参数来回滚你的事务在firts错误。所以,你需要设置WHENEVER SQLERROR EXIT ROLLBACK
http://docs.oracle.com/cd/B19306_01/server.102/b14357/ch12052.htm
您可以在这里看到一些用法例子Oracle 11 - sqlplus - rollback the whole script on error - how?
答
在这里,你可以用它来控制事务是 保持异常每个脚本,使内部处理的最佳方式如果有任何交易失败,整个更改将被恢复。这里唯一的 的条件是保持COMMIT在最后,以便在 成功的交易中最后一次灭火COMMIT。希望下面的代码 帮助。
------------------------------Script 1-----------------------------------------
--Simple query to delete from records
DECLARE
p_err_cd PLS_INTEGER;
p_err_msg VARCHAR2(100 CHAR);
BEGIN
-- EXECUTE IMMEDIATE 'DELETE EMP ';
INSERT INTO EMP
SELECT '123', 'AVRJIT', 'DB', 12, SYSDATE, 1200, 123, 10, '123' FROM DUAL;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
p_err_cd := SQLCODE;
p_err_msg:=SQLERRM;
dbms_output.put_line('Transaction Rollback');
END;
/
---------------------------------Script 2 ----------------------------------
--Simple query to delete from records
DECLARE
p_err_cd PLS_INTEGER;
p_err_msg VARCHAR2(100 CHAR);
BEGIN
-- EXECUTE IMMEDIATE 'DELETE EMP ';
INSERT INTO EMP
SELECT '123A', 'AVRJIT', 'DB', 12, SYSDATE, 1200, 123, 10, '123' FROM DUAL;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
p_err_cd := SQLCODE;
p_err_msg:=SQLERRM;
dbms_output.put_line('Transaction Rollback');
END;
/
-----------------------------------------------------------------------------
Since EMP table has EMPNO as NUMBER field so the second script will fail.
While running the main executing file i.e Full_script.sql
set serveroutput on;
@C:\Av_test_script\Stack_overflow\full_script.sql
PL/SQL procedure successfully completed.
PL/SQL procedure successfully completed. --> Failed as EMPNO column here is of Invalid datatype
Transaction Rollback
不能回滚DDL(截断是DDL),所以... – Mat
@Mat将事情改变,如果我重构“截断”到“从删除”? – user149691
是的,删除是DML,你可以从它回滚。 – sagi