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

Jan*_*vil 53 oracle plsql

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

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

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

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

Jef*_*emp 68

首先,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;
Run Code Online (Sandbox Code Playgroud)

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

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


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

BEGIN
  INSERT INTO .... ; -- first DML
  UPDATE .... ; -- second DML
  BEGIN ... END; -- some other work
  UPDATE .... ; -- final DML
END;
Run Code Online (Sandbox Code Playgroud)

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


Wol*_*olf 7

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

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

但是,您不能为嵌套块声明此pragma.你只能声明这个:

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

参考:Oracle