2015-11-05 73 views
2

按照史蒂芬斯坦书

当一个异常在PL/SQL块时,Oracle数据库不回滚 任何在该块DML语句所做的更改。你是应用程序逻辑事务的管理者,所以你决定应该发生什么样的行为。
我试试看:
DML和异常处理 - 甲骨文

CREATE TABLE DML_Exception (exception_name VARCHAR2(20)); 
INSERT INTO DML_exception VALUES('CASE_NOT_FOUND'); 
INSERT INTO DML_exception VALUES('TOO_MANY_ROWS'); 

我都行我的表

Select * from DML_Exception 

现在我从表中删除行和提高在PL/SQL块中的例外。

BEGIN 
    DELETE FROM dml_exception; 
    raise value_error; 
END; 

但我的表仍然包含两个行。我错过了什么?

+1

未提交的事务? – Stawros

+0

你在用什么客户?也许它在异常之后回滚? –

+0

作为@Stawros sadid,你忘了COMMIT – pablomatico

回答

3

您错过了本书的其他部分。是的,如果在块中发生异常,则Steven为真–,之前的所有DML效果都保留在原位。然而,本书还应该提到任何顶级SQL或PL/SQL语句(即匿名块)执行都会为该语句打开一个游标,并且如果在游标执行期间有异常,所有的DML效果都会完成在游标执行期间被回滚。也许是一个简单的例子会给你线索......

在你原来的例子,你执行...

BEGIN 
    DELETE FROM dml_exception; 
    raise value_error; 
END; 

...作为顶级声明。是的,在该块的尽头,尽管仍在,您的delete效果仍然存在。然而,你的块引发了一个传播到顶层游标的异常。因此,为了遵守atomicity的原则,Oracle回滚了打开的游标的所有挂起效果。

如果你打电话给你的PL/SQL块从另一个顶级PL/SQL块,它可以处理并不会重新提高在较低的水平,PL/SQL块产生的异常,内...

BEGIN 
    BEGIN 
     DELETE FROM dml_exception; 
     raise value_error; 
    END; 
EXCEPTION 
    WHEN others THEN NULL; 
END; 

...,那么您的delete效果应保持不变。 (并且因为在该块中没有提交,所以最终正在进行交易。)

+0

谢谢你的帮助,我的概念现在已经明确:) – Wolfgang