递归PL / SQL流水线函数CALL导致ORA-00603

时间:2018-04-06 10:50:41

标签: oracle recursion plsql pipelined-function

我是PL/SQL的新手,我想编写一个流水线功能来提取付款的通风细节(主表)。这里的代码

CREATE OR REPLACE FUNCTION F_GetImputationsReglement(Pregid Number)  RETURN 
ImputationsReglementTable PIPELINED IS

BEGIN
DECLARE
ImputationRow  Regimputation%ROWTYPE;
 type cc is REF CURSOR RETURN ImputationRow%ROWTYPE;
 cur0 cc;
 CurrentRow   ImputationRow%ROWTYPE  ;
 out_rec      ImputationReglementRow := ImputationReglementRow (null, 
null,null, null,null);
 vquery VARCHAR2(1000);
 l_result ImputationReglementRow;
BEGIN
OPEN cur0 FOR
select * from regimputation WHERE regid = pregid;
  loop
  Fetch cur0 into CurrentRow;
  EXIT WHEN cur0%NOTFOUND;
  IF CurrentRow.RIMSENS = 'C' OR CurrentRow.RIMSENS IS NULL THEN
     IF CurrentRow.facid IS NOT NULL OR (CurrentRow.facid IS NULL AND 
    CurrentRow.RIMLETTRAGE IS NULL AND CurrentRow.RUBID IS NOT NULL) THEN
        out_rec.REGID         := CurrentRow.REGID;
        out_rec.FACID         := CurrentRow.FACID;
        out_rec.RIMMT         := CurrentRow.RIMMT;
        out_rec.FECORDRE      := CurrentRow.FECORDRE;
        out_rec.RUBID         := CurrentRow.RUBID;
        PIPE ROW(out_rec);
     ELSE
        IF CurrentRow.facid IS NULL AND CurrentRow.RIMLETTRAGE is NOT null 
and CurrentRow.RUBID IS NOT NULL THEN
          vQuery := 'select * from 
table(F_GetImputationsReglement(f_getREGID('''|| CurrentRow.RIMLETTRAGE 
||''')))';
          EXECUTE IMMEDIATE vquery into l_result;
           PIPE ROW(l_result);
         END IF; 
    END IF;
  END IF;  
  END LOOP;
  CLOSE cur0;
 RETURN;
   END;
END;

退出的退出条件是:

  IF CurrentRow.RIMSENS = 'C' OR CurrentRow.RIMSENS IS NULL THEN

但是当我执行查询

select * from table(f_getimputationsReglement(696213))

我收到错误:

  
    

ORA-00603 ORACLE服务器会话因致命错误而终止

  

有没有人知道它是什么?

谢谢。

3 个答案:

答案 0 :(得分:1)

如果有机会,我会以简化的方式重写您的代码。我假设了一些东西并准备了一个简短的代码。您可以替换为实际的表列。此外,当您调用递归时,可能是代码进入无限循环并且永远不会退出并抛出您获得的错误。我共享一个简单的代码。如果您在下面看到,请参见下文,代码将在infinte recursion中。

在此示例中,var是对象的表。

CREATE OR REPLACE FUNCTION getSoccerLists
  RETURN var
IS
  --Initialization
  LIST VAR :=var();
  list1 VAR :=var();
BEGIN
  SELECT v_var( NSO ,NAME) BULK COLLECT INTO LIST FROM TEST;
  list1:= getSoccerLists;
  RETURN list;
END;

您编码重写:

考虑到你有一个对象:

CREATE TYPE v_var IS OBJECT
(
col1 NUMBER,
col1 NUMBER,
col1 number
);

Create type ImputationsReglementTable is table of v_var;


CREATE OR REPLACE  FUNCTION F_GetImputationsReglement(  Pregid NUMBER)
    RETURN ImputationsReglementTable PIPELINED
  IS
  BEGIN   
     var  ImputationsReglementTable:=ImputationsReglementTable();
     l_result ImputationsReglementTable:=ImputationsReglementTable();
    BEGIN    
      --Assuming table regimputation has col1 , col2 and col2
      SELECT * 
      BULK COLLECT INTO var
      FROM regimputation 
      WHERE regid = pregid;

      FOR i IN 1..var.count
      loop      
        IF var(i).COL1  = 'C' OR var(i).col1 IS NULL THEN

         IF var(i).col2 IS NOT NULL OR (var(i).col2 IS NULL AND var(i).col1 IS NULL AND var(i).col2 IS NOT NULL) THEN

          PIPE ROW(v_var(var(i)));          

          ELSE
          IF var(i).col1 IS NULL AND var(i).col1 IS NOT NULL AND var(i).col2 IS NOT NULL THEN
            vQuery            := 'select * from table(F_GetImputationsReglement(f_getREGID('''|| var(i).col1 ||''')))';
            EXECUTE IMMEDIATE vquery BULK COLLECT INTO l_result;
            FOR j IN 1..l_result.count
            loop
             PIPE ROW(v_var(l_result(j)));
            end loop;
          END IF;
        END IF;
      END IF;
    END LOOP;   
    RETURN;
  END;
END;

答案 1 :(得分:0)

不是您问题的答案,但我建议您在动态查询中使用绑定变量。 您可以重写以下内容以使用绑定变量:

vquery := 'select * from table(F_GetImputationsReglement(f_getREGID(''' || currentrow.rimlettrage ||
                                ''')))';
 execute immediate vquery
              into l_result;

vquery := 'select * from table(F_GetImputationsReglement(f_getREGID(:rimlettrage)))';
execute immediate vquery
            into l_result
           using currentrow.rimlettrage;

答案 2 :(得分:0)

谢谢XING的答案,但正如我所说,我是PL / SQL的新手,我没有使用BULK,所以我有很多语法错误。 我修改了我的代码如下,它工作正常:

CREATE OR REPLACE FUNCTION F_GetImputationsReglement(Pregid Number)  RETURN 
ImputationsReglementTable PIPELINED IS

BEGIN
DECLARE
 Type tmpOut  is record
(
       REGID Number(20),
       FACID Number(20),
       RIMMT NUMBER(12,3),
       FECORDRE Number(3),
       RUBID            Number(3)
);

 ImputationRow  Regimputation%ROWTYPE;
 type cc is REF CURSOR RETURN ImputationRow%ROWTYPE;
 type cc2 is REF CURSOR  return tmpOut;
 cur0 cc;
 cur00 cc2; 
 CurrentRow                          ImputationRow%ROWTYPE  ;
 out_rec                             ImputationReglementRow := 
ImputationReglementRow (null, null,null, null,null);
 CurrentRow2                        tmpOut;                   
BEGIN
OPEN cur0 FOR
select * from regimputation WHERE regid = pregid;
  loop
  Fetch cur0 into CurrentRow;
  EXIT WHEN cur0%NOTFOUND;
  IF CurrentRow.RIMSENS = 'C' OR CurrentRow.RIMSENS IS NULL THEN --Condition de sortie
     IF CurrentRow.facid IS NOT NULL OR (CurrentRow.facid IS NULL AND CurrentRow.RIMLETTRAGE IS NULL AND CurrentRow.RUBID IS NOT NULL) THEN
        out_rec.REGID         := CurrentRow.REGID;
        out_rec.FACID         := CurrentRow.FACID;
        out_rec.RIMMT         := CurrentRow.RIMMT;
        out_rec.FECORDRE      := CurrentRow.FECORDRE;
        out_rec.RUBID         := CurrentRow.RUBID;
        dbms_output.put_line('Facture ' || CurrentRow.FACID);
        PIPE ROW(out_rec);
     ELSE
        IF CurrentRow.facid IS NULL AND CurrentRow.RIMLETTRAGE is NOT null and CurrentRow.RUBID IS NOT NULL THEN
           open cur00 for 
           select * from table(F_GetImputationsReglement(f_getREGID(CurrentRow.RIMLETTRAGE)));
           loop
           Fetch cur00 into CurrentRow2;
           EXIT WHEN cur00%NOTFOUND;
           out_rec.REGID         := CurrentRow2.REGID;
           out_rec.FACID         := CurrentRow2.FACID;
           out_rec.RIMMT         := CurrentRow2.RIMMT;
           out_rec.FECORDRE      := CurrentRow2.FECORDRE;
           out_rec.RUBID         := CurrentRow2.RUBID;
           dbms_output.put_line('Facture ' || CurrentRow2.FACID);
           PIPE ROW(out_rec);
        END LOOP;
        CLOSE cur00;
    END IF;
    END IF;
  END IF;
  END LOOP;
  CLOSE cur0;
 RETURN;
END;
END;