Oracle 递归PL/SQL流水线函数调用导致ORA-00603
我是PL/SQL方面的新手,我想编写一个流水线函数来提取付款主表的详细信息。这是密码Oracle 递归PL/SQL流水线函数调用导致ORA-00603,oracle,recursion,plsql,pipelined-function,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 Imputati
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 Server会话因致命错误而终止
有人对这个有想法吗是什么
谢谢。这不是对您问题的回答,但我建议您在动态查询中使用绑定变量。 可以重写以下内容以使用绑定变量:
vquery := 'select * from table(F_GetImputationsReglement(f_getREGID(''' || currentrow.rimlettrage ||
''')))';
execute immediate vquery
into l_result;
到
如果有机会,我会用一种简单的方式重写你的代码。我做了一些假设并编写了一个简短的代码。可以替换为实际的表列。另外,当您调用递归时,代码可能会进入无限循环,并且永远不会退出并抛出您得到的错误。例如,我共享一个简单的代码。如果您喜欢下面的内容,请参见下面的内容,代码将采用infinte递归 在本例中,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;
谢谢您的回答,但正如我所说的,我是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;
服务器上的内部错误。有关错误的详细信息,请查看database alert.log。服务器很好,我对递归调用有疑问,我认为它会不确定地溢出调用堆栈。查看alert.log没有什么坏处。你可能会在那里学到一些东西,还没开始工作。我忘了提到,根据您的建议,它适用于一个简单的情况rimmletrage为null,但当它不为null时,我需要进入其他级别以提取所有细节Dear Habib…在s.O.中有一种特殊的方式表示感谢。请阅读:
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;