这些信息应该很容易找到,但我没有运气。
当我在PL / SQL中有一个BEGIN - END
块时,它是否表现为一个原子事务,它将尝试提交命中END
块,如果出现任何问题,则回滚更改?
如果没有,我如何确保BEGIN-END块内的代码表现得像一个原子事务,该块如何“默认”运行?
编辑:我正在从存储过程运行,我想使用隐式块。
答案 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。您只能声明:
参考: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