DML和异常处理 - Oracle

时间:2015-11-05 09:25:09

标签: oracle

根据Steven Feuerstein的书,
当PL / SQL块中发生异常时,Oracle数据库不会回滚 该块中DML语句所做的任何更改。您是应用程序逻辑事务的管理者,因此您决定应该发生什么样的行为 我试一试:

T(1) = 1

我的表格中有两行

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

现在我从表中删除了两行并在PL / SQL块中引发了异常。

Select * from DML_Exception

但是我的桌子仍然包含两行。我错过了什么?

1 个答案:

答案 0 :(得分:3)

你错过了本书的其他部分。是的,史蒂文是真的 - 如果一个块发生异常,所有先前的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效果将保持不变。 (并且因为该块中没有提交,所以最终会有一个正在进行的事务。)