让我们创建两个测试程序:
CREATE OR REPLACE PROCEDURE Aaaa_Test1(
pDog SYS_REFCURSOR
) IS
TYPE tDogRec is record (objid varchar2(7), lim number, debt number);
TYPE tDog IS TABLE OF tDogRec;
vDog tDog;
BEGIN
IF pDog%ISOPEN THEN
FETCH pDog BULK COLLECT INTO vDog;
IF vDog.count >= 1 THEN
FOR i IN vDog.First..vDog.Last LOOP
Dbms_Output.Put_Line('Aaaa_Test1 = '||vDog(i).Objid);
END LOOP;
END IF;
END IF;
END; -- Aaaa_Test1 Procedure
/
CREATE OR REPLACE PROCEDURE Aaaa_Test2(
pDog SYS_REFCURSOR
) IS
TYPE tDogRec is record (objid varchar2(7), lim number, debt number);
TYPE tDog IS TABLE OF tDogRec;
vDog tDog;
BEGIN
IF pDog%ISOPEN THEN
FETCH pDog BULK COLLECT INTO vDog;
IF vDog.count >= 1 THEN
FOR i IN vDog.First..vDog.Last LOOP
Dbms_Output.Put_Line('Aaaa_Test2 = '||vDog(i).Objid);
END LOOP;
END IF;
END IF;
END; -- Aaaa_Test2 Procedure
然后让我们尝试打开游标并按顺序将其传递给这些程序:
DECLARE
Vcdogcur SYS_REFCURSOR;
BEGIN
OPEN Vcdogcur FOR
select '6518535' objid, 10000 lim,0 debt
from dual
union all
select '6518536', 0,500
from dual
union all
select '5656058', 0,899
from dual
union all
select '2180965', 5000,0
from dual
union all
select '2462902', 0,100
from dual;
Aaaa_Test1(Vcdogcur);
Aaaa_Test2(Vcdogcur);
CLOSE Vcdogcur;
END;
正如您所看到的,我无法在第二个过程中使用已经获取的游标,因为ORACLE游标是向前和只读的。有哪些方法可以帮助解决这个问题?
我不能简单地将这些程序合二为一。需要保持逻辑彼此分离。
答案 0 :(得分:2)
您需要打开光标两次。使用字符串变量来保存查询将阻止您编写查询两次。
DECLARE
Vcdogcur SYS_REFCURSOR;
dyn_query varchar2(500);
BEGIN
dyn_query := 'select ''6518535'' objid, 10000 lim,0 debt
from dual
union all
select ''6518536'', 0,500
from dual
union all
select ''5656058'', 0,899
from dual
union all
select ''2180965'', 5000,0
from dual
union all
select ''2462902'', 0,100
from dual' ;
open Vcdogcur for dyn_query ;
Aaaa_Test1(Vcdogcur);
CLOSE Vcdogcur;
open Vcdogcur for dyn_query ;
Aaaa_Test2(Vcdogcur);
close Vcdogcur;
END;
/
答案 1 :(得分:2)
游标不是为了重复使用而设计的:您只需阅读它们一次,继续前进,当您这样做时,您将丢弃以前扫描过的所有行。想想Java流......这是一个功能,而不是一个错误 - 游标的内存/磁盘效率非常高。
所以选项是: 1)正如Nicolas所说,关闭并重新打开相同的光标。您将支付两次运行相同查询的性能损失 2)将查询结果存储在临时表中(适用于非常大的集合,因为它会使用磁盘) 3)将查询结果存储在一个集合中(嵌套表 - 适用于中小型表) 4)如果你真的不能做任何上面的简单解决方案,你可以尝试搞乱你的代码,这样你就有一个“调度”程序读取光标,然后将每一行传递给你的2个“工人”程序。您必须修改存储过程以便能够一次处理行