甲骨文。 重用光标在两个程序参数(Oracle. Reuse cursor as paramet

2019-10-18 10:02发布

让我们创建两个测试程序:

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的前向和后只读。 有什么办法可以帮助解决这个任务?

我不能简单地把这些程序为一体。 需要保持自己的逻辑相互独立的。

Answer 1:

你需要打开游标的两倍。 使用一个字符串变量来保存查询会阻止您编写查询两次。

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;
/


Answer 2:

游标不会设计成可重复使用:你看过他们一次,继续向前迈进,并为你这样做,你会舍弃先前扫描行。 想想一个Java流的...这是一个功能,而不是一个错误 - 光标意图是非常内存/硬盘高效。

因此,选项有:1)由于萨科提到,关闭并重新打开相同的光标。 你要付上运行相同的查询两次2)存放在一个临时表的查询结果(好非常大集,因为它会使用磁盘)3)存储在一个集合的查询结果(嵌套表的性能损失 - 为好中小型表)4)如果你真的不能做任何简单的解决方案上面,你可以用你的代码周围尝试混乱,让你有一个“调度”的程序读取光标,然后通过每个行的2“工人”手续。 你必须修改存储的特效,能够在同一时间处理行



文章来源: Oracle. Reuse cursor as parameter in two procedures