Oracle 存储过程中的提交和回滚

Pyd*_*aju 5 oracle oracle-11g plsql

在我的 Oracle 存储过程中,我有多个插入和更新语句,如下所示:

create or replace PROCEDURE SPTest
AS 
BEGIN 
  insert into emptest(empid,empname,deptno)
  (1,'ravi',10);

  insert into test1(id,name,sal)
  (1,'raju',4444);

  update emptest set empname='hari' where empid=1;
END;
Run Code Online (Sandbox Code Playgroud)

如果我在任何语句中遇到任何错误,我想回滚所有插入和更新语句。

如何在此存储过程中实现提交和回滚?

SQB*_*SQB 8

您可以通过使用保存点来做到这一点。

CREATE OR REPLACE PROCEDURE SPTest
AS 
BEGIN
   -- We create a savepoint here.
   SAVEPOINT sp_sptest;
   
   INSERT INTO emptest(empid, empname, deptno)
   VALUES(1, 'ravi', 10);
   
   INSERT INTO test1(id, name, sal)
   VALUES(1, 'raju', 4444);
   
   UPDATE emptest
   SET empname = 'hari'
   WHERE empid = 1;
   
-- If any exception occurs
EXCEPTION
   WHEN OTHERS THEN
      -- We roll back to the savepoint.
      ROLLBACK TO sp_sptest;
      
      -- And of course we raise again,
      -- since we don't want to hide the error.
      -- Not raising here is an error!
      RAISE;
END;
Run Code Online (Sandbox Code Playgroud)

提交通常留给调用者。这个结构只是保证所有的插入和更新都完成,或者都不完成。

在最外层,Oracle 会自己做一个回滚。换句话说,如果你EXEC sptest();在 SQL+ 命令行上做,它会自动扩展为

DECLARE
BEGIN
   sptest();
EXCEPTION
   ROLLBACK;
   RAISE;
END;
Run Code Online (Sandbox Code Playgroud)

但是如果调用过程有异常处理,则不会发生这种情况,因为异常可能不会到达该外部级别。因此,您最终可能会完成插入,更新会抛出一个异常,该异常可能会被调用者捕获并处理,因此更新将失败但插入成功。

通过在存储过程中回滚到过程的开头,您可以确保所有这些都成功,或者没有一个成功。