PLSQL异常中的回滚

时间:2011-11-22 21:53:55

标签: sql oracle exception-handling plsql

想知道在检测到SQL异常(其他人的异常)时是否需要回滚:

declare
 cursor c_test is
    select    *
    from  tesing;
    begin
       for rec in c_test loop
       begin
           update test1 set test1.name=rec.name where test1.id=rec.id;
           IF sql%rowcount = 1 THEN
                            commit;
           ELSIF   sql%rowcount =0 THEN
                   dbms_output.put_line('No Rows Updated');
           else
                  dbms_output.put_line('More than 1 row exists');
                  rollback;
           END IF;
       exception when others then
                  dbms_output.put_line(Exception');
                  rollback;
      end;      

end;

1 个答案:

答案 0 :(得分:16)

首先,我假设我们可以忽略语法错误(例如,没有END LOOPdbms_output.put_line调用缺少第一个单引号等。)

至于是否有必要回滚更改,这取决于。

通常,您不会在循环中进行临时提交。这通常是一种糟糕的架构,因为它在I / O和耗用时间方面成本更高。它还使编写可重新启动的代码变得更加困难。例如,如果您的SELECT语句选择10行,您发出(并提交)5个更新,然后第6次更新失败,会发生什么?在修复异常后,能够在第6行重新启动的唯一方法是使用单独的表来存储(并更新)代码的进度。它还会为调用此块的任何代码创建问题,然后必须处理一半工作已完成(并已提交)而另一半未完成的情况。

通常,您只需将事务控制语句放在代码的最外层块中。由于过程中的COMMITROLLBACK提交或回滚在会话中完成的任何工作,无论是否由过程完成,您都希望在添加事务控制语句时非常谨慎。您通常希望让调用者确定是提交还是回滚。当然,这只是到目前为止 - 最终,你将成为永远不会从其他一些例程调用的最外层的块,你需要有适当的事务控制 - 但这是非常谨慎的事情关于你是否正在编写可能被重用的代码。

在这种情况下,由于您有临时提交,因此ROLLBACK的唯一影响是,如果第一个更新语句失败,则在调用此块之前在会话中完成的工作将被滚动背部。如果第一个更新语句成功,临时提交将提交先前的更改。当他们谈论为什么临时提交和可重用块中的事务控制存在问题时,人们会担心这种副作用。