想知道在检测到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;
答案 0 :(得分:16)
首先,我假设我们可以忽略语法错误(例如,没有END LOOP
,dbms_output.put_line
调用缺少第一个单引号等。)
至于是否有必要回滚更改,这取决于。
通常,您不会在循环中进行临时提交。这通常是一种糟糕的架构,因为它在I / O和耗用时间方面成本更高。它还使编写可重新启动的代码变得更加困难。例如,如果您的SELECT
语句选择10行,您发出(并提交)5个更新,然后第6次更新失败,会发生什么?在修复异常后,能够在第6行重新启动的唯一方法是使用单独的表来存储(并更新)代码的进度。它还会为调用此块的任何代码创建问题,然后必须处理一半工作已完成(并已提交)而另一半未完成的情况。
通常,您只需将事务控制语句放在代码的最外层块中。由于过程中的COMMIT
或ROLLBACK
提交或回滚在会话中完成的任何工作,无论是否由过程完成,您都希望在添加事务控制语句时非常谨慎。您通常希望让调用者确定是提交还是回滚。当然,这只是到目前为止 - 最终,你将成为永远不会从其他一些例程调用的最外层的块,你需要有适当的事务控制 - 但这是非常谨慎的事情关于你是否正在编写可能被重用的代码。
在这种情况下,由于您有临时提交,因此ROLLBACK
的唯一影响是,如果第一个更新语句失败,则在调用此块之前在会话中完成的工作将被滚动背部。如果第一个更新语句成功,临时提交将提交先前的更改。当他们谈论为什么临时提交和可重用块中的事务控制存在问题时,人们会担心这种副作用。