0

在下面的示例中,我有一个 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;
/
4

1 回答 1

0

这段代码有几个问题。

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

第二个错误是一个微妙的错误。检查游标%notfound是 LIMIT 子句的一个问题,因为true当游标返回少于限制的任意数量的记录时,它会计算结果:%notfound即使游标返回 99 条记录也是如此。这是 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层时它已经耗尽。有几种方法可以解决这个问题,具体取决于您想要实现的目标。发布有关您的逻辑的更多详细信息。

于 2020-12-11T11:13:54.297 回答