【问题标题】:Make a PL/SQL stored procedure roll back all changes when an exception occurs?发生异常时,使 PL/SQL 存储过程回滚所有更改?
【发布时间】:2015-11-25 16:21:34
【问题描述】:

我有一个程序可以对不同的表进行多次更新。如果过程中的任何地方发生任何错误,我希望所有更改都回滚。因此我使用了这个结构:

CREATE PROCEDURE foo (x NUMBER) IS
BEGIN
  -- Do some inserts here.
  INSERT INTO bar VALUES (x);
  -- Sometimes there might be an error.
  IF x = 3 THEN
    RAISE_APPLICATION_ERROR(-20000, 'Wooops...');
  END IF;
EXCEPTION
  WHEN OTHERS THEN
    --Rollback all the changes and then raise the error again.
    ROLLBACK;
    RAISE;
END foo;

问题在于,这会回滚自上次提交以来所做的所有事情,而不仅仅是过程所做的更改。例如,这将插入 4 和 5,但 1 和 2 将被回滚:

BEGIN
  FOR x IN 1..5 LOOP
    BEGIN
      foo(x);
    EXCEPTION
      WHEN OTHERS THEN
        NULL;
    END;
  END LOOP;
END;

如何让程序仅回滚在此调用期间程序所做的更改?我想我应该以某种方式使用事务,但我不确定如何设置它。

请注意,我想在过程的代码中解决这个问题,而不是在调用它的代码中。

【问题讨论】:

标签: oracle stored-procedures plsql transactions rollback


【解决方案1】:

在 Oracle 中,您可以使用 SAVEPOINTS。应该是这样的:

CREATE PROCEDURE foo (x NUMBER) IS
BEGIN
  SAVEPOINT update_bar;

  -- Do some inserts here.
  INSERT INTO bar VALUES (x);
  -- Sometimes there might be an error.
  IF x = 3 THEN
    RAISE_APPLICATION_ERROR(-20000, 'Wooops...');
  END IF;
EXCEPTION
  WHEN OTHERS THEN
    -- Rollback everything which was made after `SAVEPOINT update_bar`
    ROLLBACK TO update_bar;
    RAISE;
END foo;

【讨论】:

  • 你还需要添加一个 COMMIT 吗?
  • 如果你喜欢提交是的
  • 感谢您的回答!由于每次调用该过程都会在同一时间创建一个保存点,是否会出现任何问题?还是 Oracle 会在程序完成后忘记保存点?
  • 谢谢!我已经尝试过了,它会插入 1、2、4、5,就像它应该插入的那样。由于我不在循环中的过程调用之间进行提交,我猜它只是回滚到名为 update_bar 的最新保存点。
猜你喜欢
  • 2021-11-29
  • 2010-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多