提取失序<ora-01002>回滚

时间:2017-02-17 09:55:56

标签: sql oracle plsql

今天我遇到了“FETCH OUT OF SEQUENCE”ORA-01002。我已经做了很多研究,并且我开始明白,当我们这样做时,它很常见。

  1. 尝试在我们已经关闭光标时获取。
  2. 用于更新和提交。
  3. 如果成功处理,我的要求是提交每500条记录,如果出现任何问题,则回滚所提取的500条记录。

    我没有做过其中任何一个。我还发现由于ROLLBACK导致序列失序;

    我还缩小到实际发生的时间。只有在第一组记录发生回滚时才会发生这种情况。

       loop
        Fetch c1 bulk collect into type1 limit 500;
        exit when type1.count=0;
        forall in i..type1.count save exceptions 
        insert into the table.
        do something.....
        the computation goes on;
        Commit;
        exception when others then 
        for i in 1..sql%bulk_exceptions loop 
        Do somthing...
        end loop;
        rollback; => Fetch out of seq happens here...
       end loop;
    

    只有当前500条记录失败并且我发出回滚命令时,才会发生失序。当前500条记录被提交时,它不会给ora-01002,并且接下来的500条记录被回滚。

    为什么这样做的原因。请建议是否有任何方法不要避免ora-01002错误。

    由于公司政策的原因,抱歉无法在此发布编码。但上面给出的伪代码是编码的方式。

    其他信息 - &gt;如果我以这种方式执行程序,那么我没有收到错误“ORA-01002”。

    loop
    Fetch c1 bulk collect into type1 limit 500;
    exit when type1.count=0;
    COMMIT; => IF I ADD COMMIT HERE ORA-01002 doesnt appear. 
    forall in i..type1.count save exceptions 
    insert into the table.
    do something.....
    the computation goes on;
    Commit;
    exception when others then 
    for i in 1..sql%bulk_exceptions loop 
    Do somthing...
    end loop;
    rollback; => Fetch out of seq happens here...
    

    结束循环;

2 个答案:

答案 0 :(得分:2)

此错误表示已尝试从不再valid的游标进行提取。请注意,PL / SQL游标循环隐式执行提取,因此也可能导致此错误。导致此错误的原因有很多,包括:

1)在检索到最后一行之后从游标中获取并返回ORA-1403错误。

2)如果已使用FOR UPDATE子句打开游标,则在发出COMMIT之后获取将返回错误。

3)重新绑定SQL语句中的任何占位符,然后在重新执行语句之前发出提取。

行动:

1)在检索到最后一行之后不要发出fetch语句 - 不再需要获取行。

2)不要为已经打开FOR UPDATE的游标在fetch循环内发出COMMIT。

3)重新绑定后重新执行该语句,然后再次尝试获取。

ORA-01002可能有多种原因,包括:

•PL / SQL循环确实在没有通知的情况下进行提取

•尝试从不再有效的游标中获取(从已检索的行中获取)。

•在已发出COMMIT并使用FOR UPDATE子句打开游标后进行提取。

•在重新绑定占位符后重新执行SQL之前发出提取。

您可能希望将来尝试使用游标属性来躲避ORA-01002。

要解决当前的ORA-01002,您可以执行三项操作:

1.收到最后一条记录后,请勿发出提取

2.在SELECT FOR UPDATE上的取指循环中,不要使用COMMIT

3.重新执行语句后重新获取(重新绑定后)

来源:ora-01002

答案 1 :(得分:2)

当您以这种方式处理记录时,在处理过程中不应该有commit / rollback这样的记录。 Rollback无效的当前光标。在任何情况下,您都应该在500条记录之后提交,并处理异常。

一旦你回滚,Oracle就无法回想它的光标所在的位置。

this example的声明7一样,您应该处理FORALL的单一例外情况

--- declare exception
failure_in_forall   EXCEPTION;  
PRAGMA EXCEPTION_INIT (failure_in_forall, -24381);  

...
-- handle it
EXCEPTION   
        WHEN failure_in_forall 
  ...

然后,您的好记录将被处理和提交,而坏的记录将在稍后进行审核和处理