1

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

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

我不能简单地将这些程序合二为一。需要将它们的逻辑彼此分开。

4

2 回答 2

3

游标不是为重复使用而设计的:您阅读它们一次,继续前进,当您这样做时,您将丢弃任何以前扫描的行。想想 Java 流...这是一个特性,而不是错误 - 游标旨在提高内存/磁盘效率。

所以选项是:1)正如尼古拉斯所说,关闭并重新打开同一个光标。您将支付两次运行相同查询的性能损失 2) 将查询结果存储在临时表中(适用于非常大的集合,因为它会使用磁盘) 3) 将查询结果存储在集合中(嵌套表 - 适用于中小型表) 4)如果你真的不能做上面的任何简单的解决方案,你可以尝试弄乱你的代码,这样你就有一个“调度”程序来读取光标,然后将每一行传递给你的2“工人”程序。您必须修改存储的过程才能一次处理行

于 2013-07-31T13:34:22.823 回答
3

您需要打开游标两次。使用字符串变量来保存查询将阻止您编写两次查询。

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;
/
于 2013-07-29T16:25:03.290 回答