0

只是想知道如果我们内部有异常捕获,我们是否真的需要在 LOOP 语句中需要回滚/保存点。

create table my_Tab
(id number,
name varchar2(10),
address varchar2(100));

insert into my_tab values (1,'ABC','XXX');
insert into my_tab values (2,'DEF','YYY');
insert into my_tab values (3,'GHI','ZZZ');
insert into my_tab values (4,'JKL',null);

DECLARE
CURSOR cur_my_tab is
select * from my_tab;
l_var varchar2(100);
l_count number := 0;
begin
for rec_my_tab in cur_my_tab
loop
    BEGIN
    dbms_output.put_line('id' || rec_my_tab.id);
    --savepoint sv_cur_my_tab;
        dbms_output.put_line('name' || rec_my_tab.name);
        select rec_my_tab.address into l_var from dual;
        update my_Tab set id = id +4 where id = rec_my_tab.id;
        dbms_output.put_line(l_var);
        if rec_my_tab.address ='xxx' then
            l_count:= rec_my_tab.id/l_count;
        END IF;
    Exception
        when others then 
            dbms_output.put_line('in inner exception');
            --rollback to sv_cur_my_tab;*/
    end;
end loop;
Exception
    when others then 
        dbms_output.put_line('in outer exception');
        --rollback to sv_cur_my_tab;
end;

我在查询上方有 2 个查询。

  1. 提交何时按上述顺序发生。
  2. 在上面的代码中,考虑在光标中间抛出异常(如第 3 次或第 4 次迭代)。添加回滚和保存点会对此进行更改吗?目前,整个循环已完成,所有更新也正在提交。
4

1 回答 1

1

什么时候提交按上述顺序发生?

它没有。至少,我没有看到任何commit声明。也许我是个盲人。但是 PL/SQL 中没有“自动提交”。因此,在commit您发布一个(或您的客户端软件发布)之前不会发生。

在上面的代码中,考虑在光标中间抛出异常(如第 3 次或第 4 次迭代)。添加回滚和保存点会对此进行更改吗?目前,整个循环已完成,所有更新也正在提交。

当您在游标循环中有多个DML 语句并且您俩都使用时,回滚到保存点通常很有用

  1. 希望确保,对于每个游标记录,DML 语句要么全部成功,要么都不成功
  2. 在处理完所有行之前不想提交任何内容

在您的情况下,update循环内只有一个,然后更改“l_count”变量的值。如果您希望在更改“l_count”时出现任何问题时回滚更新,则您需要回滚到保存点。

请记住,回滚到保存点不会恢复对 PL/SQL 变量的任何更改,例如“l_count”。在回滚到保存点之前,您有责任根据需要恢复它们的值。

于 2020-03-02T19:48:33.887 回答