fre*_*oft 2 oracle plsql exception rollback
在Oracle Database PL/SQL语言参考11g第2版(11.2)文档中,"隐式回滚"部分以此文本开头:
"在运行INSERT,UPDATE,DELETE或MERGE语句之前,数据库标记一个隐式保存点(对您不可用).如果语句失败,数据库将回滚到保存点.通常,只会回滚失败的SQL语句,不是整个交易."
因此,如果我将一个SQL语句运行到PL/SQL程序中,并且句子失败,那么该句子将自动回滚.那没问题.
但同一部分以本文结尾:
"如果退出存储的子程序时出现未处理的异常,PL/SQL不会为OUT参数赋值,也不会进行任何回滚."
它似乎与第一个文本相反:如果我的程序以未捕获的异常结束,则不执行回滚.但是第一篇文章说如果SQL语句失败,则会自动完成回滚.
因此,如果我的存储程序包含一个SQL语句,句子失败,异常没有被捕获,我的程序结束,那么SQL语句应该回滚吗?该文件是否有矛盾?
Stack Overflow中的相关问题:
更新(已解决):感谢DrabJay的示例,现在更清楚了:
失败的SQL语句的回滚总是完成(无论是否进入程序).程序的回滚取决于调用者:
如果程序是一个匿名块(无来电显示存在),它相当于从用户的语句被调用,而一个失败的用户语句回自动回滚,所以匿名块被回滚.
我认为该文件应该更清楚,特别是"并且不做任何回滚"这两个词:
"如果退出存储的子程序时出现未处理的异常,PL/SQL不会为OUT参数赋值,也不会进行任何回滚."
没有矛盾,但必须准确阅读文档e,.g.
CREATE TABLE t
(col NUMBER(1) NOT NULL)
/
Table created.
CREATE PROCEDURE insert_t1
AS
BEGIN
INSERT INTO t
(col)
SELECT 1 FROM dual
UNION ALL
SELECT 2 FROM dual;
INSERT INTO t
(col)
SELECT 9 FROM dual
UNION ALL
SELECT 10 FROM dual;
END;
/
Procedure created.
SELECT col
FROM t
/
no rows selected.
INSERT INTO t
SELECT 9 FROM dual
UNION ALL
SELECT 10 FROM dual
/
INSERT INTO t
*
ERROR at line 1:
ORA-01438: value larger than specified precision allowed for this column
SELECT col
FROM t
/
no rows selected.
Run Code Online (Sandbox Code Playgroud)
这表明,假设插入两个记录的尝试是按指定的顺序,DML语句回滚到执行语句之前建立的隐式保存点,因为数据库中不存在任何记录.如果我们继续:
SET SERVEROUTPUT ON SIZE 1000000
DECLARE
CURSOR csr
IS
SELECT col
FROM t
ORDER BY col;
BEGIN
BEGIN
insert_t1;
EXCEPTION
WHEN OTHERS THEN
FOR rec IN csr LOOP
dbms_output.put_line('COL: ' || rec.col);
END LOOP;
RAISE;
END;
END;
/
COL: 1
COL: 2
DECLARE
*
ERROR at line 1:
ORA-01438: value larger than specified precision allowed for this column
ORA-06512: at line 15
Run Code Online (Sandbox Code Playgroud)
这表明如果退出存储的子程序带有未处理的异常,Oracle不会进行任何回滚,因为第一个insert语句插入的记录仍在表中.但是,如上所述,直接执行DML时,整个第二个insert语句已回滚到执行第二个语句之前建立的隐式保存点.
但是,如果我们然后尝试查询表.
SELECT col
FROM t
/
no rows selected.
Run Code Online (Sandbox Code Playgroud)
这表明如果退出带有未处理异常的匿名块,Oracle确实会进行回滚.这将再次是在执行匿名块之前建立的隐式保存点.
| 归档时间: |
|
| 查看次数: |
758 次 |
| 最近记录: |