BEGIN - END阻止PL / SQL中的原子事务

时间:2012-08-15 08:16:08

标签: oracle plsql

这些信息应该很容易找到,但我没有运气。

当我在PL / SQL中有一个BEGIN - END块时,它是否表现为一个原子事务,它将尝试提交命中END块,如果出现任何问题,则回滚更改?

如果没有,我如何确保BEGIN-END块内的代码表现得像一个原子事务,该块如何“默认”运行?

编辑:我正在从存储过程运行,我想使用隐式块。

4 个答案:

答案 0 :(得分:65)

首先,BEGIN..END只是句法元素,与事务无关。

其次,在Oracle中,所有单独的DML语句都是原子的(即它们要么完全成功,要么在第一次失败时回滚任何中间更改)(除非你使用EXCEPTIONS INTO选项,我不会在这里讨论)。

如果您希望将一组语句视为单个原子事务,您可以执行以下操作:

BEGIN
  SAVEPOINT start_tran;
  INSERT INTO .... ; -- first DML
  UPDATE .... ; -- second DML
  BEGIN ... END; -- some other work
  UPDATE .... ; -- final DML
EXCEPTION
  WHEN OTHERS THEN
    ROLLBACK TO start_tran;
    RAISE;
END;

这样,任何异常都会导致回滚此块中的语句,但不会回滚在此块之前运行的任何语句

请注意,我没有包含COMMIT - 通常我更喜欢调用进程来发出提交。


确实没有异常处理程序的BEGIN..END块会自动为您处理:

BEGIN
  INSERT INTO .... ; -- first DML
  UPDATE .... ; -- second DML
  BEGIN ... END; -- some other work
  UPDATE .... ; -- final DML
END;

如果引发异常,将回滚所有插入和更新;但是只要您想添加异常处理程序,它就不会回滚。所以我更喜欢使用保存点的显式方法。

答案 1 :(得分:6)

BEGIN - END块是PL / SQL的构建块,每个PL / SQL单元至少包含在一个这样的块中。在PL / SQL块中嵌套BEGIN - END块通常用于捕获某些异常并处理该特殊异常,然后引发不相关的异常。然而,在PL / SQL中,您(客户端)必须始终为事务发出提交或回滚。

如果您希望在包含PL / SQL的事务中包含原子事务,则需要在声明块中声明PRAGMA AUTONOMOUS_TRANSACTION。这将确保该块中的任何DML都可以独立于包含事务提交或回滚。

但是,您无法为嵌套块声明此pragma。您只能声明:

  • 顶级(非嵌套)匿名PL / SQL块
  • 列表项
  • 本地,独立和打包的功能和程序
  • SQL对象类型的方法
  • 数据库触发器

参考:Oracle

答案 2 :(得分:0)

你没有提到这是一个匿名的PL / SQL块还是一个声明的块,即。包装,程序或功能。 但是,在PL / SQL中,必须明确地进行COMMIT以将事务保存到数据库。 COMMIT实际上将所有未保存的事务从当前用户的会话保存到数据库。

如果发生错误,则事务隐式执行ROLLBACK。

这是PL / SQL的默认行为。

答案 3 :(得分:0)

Commit PL / SQL块的默认行为:

您应该显式提交或回滚每个事务。在PL / SQL程序中还是从客户端程序发出提交或回滚取决于应用程序逻辑。如果您未明确提交或回滚事务,则客户端环境将确定其最终状态。

例如,在SQL Plus环境中,如果您的PL / SQL块 不包含COMMIT或ROLLBACK语句,则您的最终状态 事务取决于您运行该块之后的操作。如果你 执行数据定义,数据控件或COMMIT语句,或者 发出EXIT,DISCONNECT或QUIT命令,Oracle提交 交易。如果执行ROLLBACK语句或中止SQL Plus 会话中,Oracle将回滚该事务。

https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/sqloperations.htm#i7105