【问题标题】:Getting ORA-01002:fetch out of sequence error when doing Bulk-collect获取 ORA-01002:进行批量收集时出现失序错误
【发布时间】:2021-03-22 16:03:34
【问题描述】:

在下面的示例中,我有一个 SP,它将一个 SYS_REFCURSOR 作为 OUT 参数返回给 Java 服务,并且在同一个 SP 中,它将 SYS_REFCURSOR 结果插入到另一个表示例 -temp。当我执行 SP 时,它给出了一个错误

ORA-01002 : 提取乱序错误

我确实看到数据被插入,但服务没有向服务返回任何 REFCURSOR。

create or replace procedure ins_act(l_result        OUT        sys_refcursor)
as 

 --Created a RECORD type to hold the result of the SYS_REFCURSOR
 TYPE RSLT IS RECORD
 (

 l_id1                   varchar2(32),
 l_id2                   varchar2(32),
 l_id3                   varchar2(32),
 l_pid                   varchar2(16),
 l_ac                    varchar2(32),
 l_activity_date         varchar2(32),
 l_file_id               varchar2(64)
 ) ;

 --Created associative array to hold the result
 Type v_reslt is table of RSLT index by PLS_INETEGER;

 --Variable to Record type
 var_reslt   v_reslt;

begin
          -- Procedure to pull the get records 
          OPEN l_result FOR 
             SELECT COL1,COL2,COL3,CoUnt(*).....
             

          -- Bulk fetch
          Loop

          fetch l_result bulk collect into  var_reslt limit 100;         

          --Bulk Insert     
          FORALL I INTO 1..var_reslt.count SAVE EXCEPTIONS
          insert into temp(id1,
                           id2,
                           id3,
                           platform_id,
                           activity_code,
                           update_timestamp,
                           file_id)          
          values 
             (to_char(to_date(var_reslt(i).l_id1,'mm/dd/yyyy'),'mm/dd/yyyy'),
              var_reslt(i).l_id2,
              var_reslt(i).l_id3,
              0,
              var_reslt(i).l_ac,
              var_reslt(i).l_activity_date,
              var_reslt(i).l_file_id);

         exit when l_result%notfound; 

      end loop;

   Commit;

  close l_result;

Exception
 WHEN OTHERS
   THEN    
         --Bulk Exception handling
         FOR indx IN 1 .. SQL%BULK_EXCEPTIONS.COUNT
         LOOP
            DBMS_OUTPUT.put_line (
                  SQL%BULK_EXCEPTIONS (indx).ERROR_INDEX
               || ‘: ‘
               || SQL%BULK_EXCEPTIONS (indx).ERROR_CODE);
         RAISE;          
end;
/

【问题讨论】:

    标签: oracle stored-procedures plsql sys-refcursor bulk-collect


    【解决方案1】:

    这段代码有几个问题。

    首先是检查游标是否在 FORALL 语句之后找到任何内容。这是错误的,因为即使游标为%notfound,FORALL 语句也会尝试处理游标。这可能是您的 ORA-01002 异常的来源。

    第二个错误是一个微妙的错误。检查游标%notfound 是LIMIT 子句的一个问题,因为当游标返回的记录数少于限制时,它的计算结果为true:即使游标返回99 条记录,它也会是%notfound。这是 PL/SQL 实现的一个非直观方面。无论如何,最好检查集合中的条目数。

    这是针对这两个问题修复的代码:

    create or replace procedure ins_act(l_result        OUT        sys_refcursor) as 
    
     TYPE RSLT IS RECORD  (
     l_id1                   varchar2(32),
     l_id2                   varchar2(32),
     l_id3                   varchar2(32),
     l_pid                   varchar2(16),
     l_ac                    varchar2(32),
     l_activity_date         varchar2(32),
     l_file_id               varchar2(64)) ;
    
     Type v_reslt is table of RSLT index by PLS_INETEGER;
     var_reslt   v_reslt;
    
    begin
              OPEN l_result FOR 
                 SELECT COL1,COL2,COL3,CoUnt(*).....
              Loop
    
              fetch l_result bulk collect into  var_reslt limit 100;          
              
              exit when var_reslt.count() = 0; 
    
              --Bulk Insert     
              FORALL I INTO 1..var_reslt.count SAVE EXCEPTIONS
              insert into temp(id1,
                               id2,
                               id3,
                               platform_id,
                               activity_code,
                               update_timestamp,
                               file_id)          
              values 
    (to_char(to_date(var_reslt(i).l_id1,'mm/dd/yyyy'),'mm/dd/yyyy'),
                  var_reslt(i).l_id2,
                  var_reslt(i).l_id3,
                  0,
                  var_reslt(i).l_ac,
                  var_reslt(i).l_activity_date,
                  var_reslt(i).l_file_id);
          end loop;
       Commit;
       close l_result;
    
    Exception
     WHEN OTHERS
       THEN    
             --Bulk Exception handling
             FOR indx IN 1 .. SQL%BULK_EXCEPTIONS.COUNT
             LOOP
                DBMS_OUTPUT.put_line (
                      SQL%BULK_EXCEPTIONS (indx).ERROR_INDEX
                   || ‘: ‘
                   || SQL%BULK_EXCEPTIONS (indx).ERROR_CODE);
             RAISE;          
    end;
    /
    

    最后的错误是程序性的。 refcursor 是一次性镜头。你在程序中读取它,这意味着当你将它传递回java层时它已经耗尽。有几种方法可以解决这个问题,具体取决于您想要实现的目标。发布有关您的逻辑的更多详细信息。

    【讨论】:

    • 我的要求是将 sys_refcursor C1 返回到服务并将相同的 sys_refcursor C1 插入到另一个表中。我尝试进行上述更改,但仍然出现 fetch out of sequence 错误
    • 您的实际代码与您发布的代码有多接近?显然,您已经编辑了 SELECT 语句的投影:您是否简化了其他位、省略了循环等?因为很难看出发布的代码如何抛出 ORA-01002(我发送的东西可能会抛出它是一个猜测:我还没有看到由使游标无效的特定方法引起的 ORA-01002)。
    猜你喜欢
    • 2013-09-07
    • 2016-06-09
    • 1970-01-01
    • 2013-04-19
    • 2016-07-11
    • 1970-01-01
    • 2023-03-04
    相关资源
    最近更新 更多