在文档Oracle数据库PL/SQL语言参考资料11g第2版(11.2)中,“隐式回滚”部分以以下文本开头:
在运行INSERT、UPDATE、DELETE或MERGE语句之前,数据库标记一个隐式保存点(您无法使用)。如果语句失败,数据库将回滚到保存点。通常,只回滚失败的语句,而不是整个事务。
因此,如果我在PL/SQL程序中运行一个SQL语句,而这个句子失败了,那么这个句子就会自动回滚。这没什么。
但同一节以以下案文结尾:
“如果使用未处理的异常退出存储的子程序,则PL/SQL不为OUT参数赋值,而不执行任何回滚。”
这似乎与第一个文本相反:如果我的程序以未捕获的异常结束,则不会执行回滚操作。但是第一个文本指出,如果SQL语句失败,回滚就会自动完成。
因此,如果存储的程序包含SQL语句,则该语句将失败,异常不会被捕获,并且我的程序结束,那么SQL语句是否应该回滚?这份文件有矛盾吗?
堆栈溢出中的相关问题:
Update (solved):感谢DrabJay的示例,现在更清楚了:
失败的SQL语句的回滚总是完成(独立于程序中)。程序的回滚取决于调用方:
如果程序是匿名块(不存在调用方),则相当于从user语句调用,失败的用户语句自动回滚,因此匿名块被回滚。
我认为这份文件应更清楚,特别是在“而不作任何回滚”的字眼上:
“如果使用未处理的异常退出存储的子程序,则PL/SQL不会为OUT参数()分配值,也不会执行任何回滚。”
发布于 2014-09-04 17:51:58
没有矛盾,但文档必须精确地阅读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.这表明,假设尝试插入两个记录的顺序是指定的,则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这表明,如果您退出带有未处理异常的存储的子程序,则Oracle不会执行任何回滚操作,因为第一个insert语句插入的记录仍然在表中。但是,如上所述,在直接执行DML时,第二个insert语句的全部回滚到执行第二个语句之前建立的隐式保存点。
但是,如果我们随后尝试查询表。
SELECT col
FROM t
/
no rows selected.这表明,如果退出带有未处理异常的匿名块,则Oracle会执行回滚操作。这将同样适用于在执行匿名块之前建立的隐式保存点。
https://stackoverflow.com/questions/25666826
复制相似问题