ORA-01002: for 循环和更新语句导致获取不正确的序列

问题描述 投票:0回答:1

我有一个目前在 Oracle Database 19C 中看起来像这样的过程

Declare
 i integer;
BEGIN
  Delete from t_invent;
  -- If I add commit here or remove the delete statement here then the error wouldnt occurred.

  FOR r_in IN (SELECT * FROM t_in) LOOP
  
    -- Insert into another table
    INSERT INTO t_invent (item_id, item_name) VALUES (r_in.item_id, r_in.item_name);
    
    -- Rollback the transaction
    if r_in.count = 90 then
       ROLLBACK; 
       -- Rollback here would cauase the procedure show this error ORA-01002: Fetch out of Sequence.
    end if;
    
  END LOOP;

END;

根据我的进一步测试,我发现如果我在 for 循环之前添加 Commit,则在这种情况下不会出现获取乱序问题下方的回滚。

另一方面,我在这个问题上添加了dbms_output.put_line来跟踪,我发现回滚不会直接让整个for循环崩溃,有时它可以继续循环12个数据然后它会崩溃。

基于此错误的 Oracle 文档 - ORA-01002:Fetch out of Sequence。 https://docs.oracle.com/en/error-help/db/ora-01002/?r=19c 它表明游标无效会让Oracle显示此错误。

此外,在 for 循环中添加提交(例如大约 50 个数据,然后提交)可以解决此问题,但如果我增加到 100 个数据,则错误将再次显示。

看来回滚和提交会对游标产生影响。

我怀疑for循环中的回滚会回滚事务以及上面的删除语句。但是我不知道为什么游标无效,因为我没有在此表上执行任何 DML (t_in)

以前有人遇到过这个问题吗?有人对这种行为有任何想法吗?

oracle exception plsql rollback oracle19c
1个回答
0
投票

您可以抛出异常并在捕获异常时回滚,而不是尝试在循环内回滚:

DECLARE
  needs_rollback EXCEPTION;
  PRAGMA EXCEPTION_INIT(needs_rollback, -20001);
BEGIN
  Delete from t_invent;

  FOR r_in IN (SELECT * FROM t_in) LOOP
  
    -- Insert into another table
    INSERT INTO t_invent (item_id, item_name) VALUES (r_in.item_id, r_in.item_name);
    
    -- Rollback the transaction
    if r_in.count = 90 then
       --ROLLBACK; 
       raise needs_rollback;
    end if;
    
  END LOOP;

EXCEPTION
  WHEN needs_rollback THEN
    rollback;
END;
© www.soinside.com 2019 - 2024. All rights reserved.