获取Oracle中的ref游标数

时间:2013-11-25 23:21:16

标签: oracle cursor

我有一个返回ref cursor作为输出参数的过程。我需要找到一种方法来获取光标中no.of记录的计数。目前我通过重复相同的选择查询来获取计数,这会影响性能。

例如:

create or replace package temp 
TYPE metacur IS REF CURSOR;

PROCEDURE prcSumm (
pStartDate          IN          DATE,
pEndDate            IN          DATE,
pKey        IN          NUMBER,
pCursor             OUT         metacur
) ;

  package body temp is

  procedure prcSumm(  
  pStartDate          IN          DATE,
  pEndDate            IN          DATE,
  pKey        IN          NUMBER,
  pCursor             OUT         metacur
   )
 IS
 vCount NUMBER;

 BEGIN

  vCount := 0;

select count(*) into vCount
   from customer c, program p, custprog cp
   where c.custno = cp.custno
   and cp.programid = p.programid
   and p.programid = pKey
   and c.lastupdate >= pStartDate
   and c.lastupdate < pEndDate;

 OPEN pCursor for SELECT 
  c.custno, p.programid, c.fname, c.lname, c.address1, c.address2, cp.plan               
   from customer c, program p, custprog cp
   where c.custno = cp.custno
   and cp.programid = p.programid
   and p.programid = pKey
   and c.lastupdate >= pStartDate
   and c.lastupdate < pEndDate;
    end prcSumm;

有没有办法将out光标中的no.of行转换为vCount。

谢谢!

1 个答案:

答案 0 :(得分:2)

通常,Oracle不知道从游标中获取多少行,直到最后一次获取找不到要返回的行。由于Oracle不知道将返回多少行,因此您无法获取所有行(正如您在重新运行查询时所做的那样)。

除非您使用单用户系统或使用非默认事务隔离级别(这会引入其他复杂性),否则无法保证游标返回的行数和{{1第二个查询返回匹配。完全可能的是,另一个会话在您打开游标的时间和运行count(*)的时间之间进行了更改。

如果您确实想要生成准确的计数,可以将count(*)列定义为cnt列到您用来打开游标的查询中。然后,游标中的每一行都会有一列count(*) over (),它会告诉您将返回的总行数。 Oracle必须做更多的工作才能生成cnt,但它比两次运行相同的查询要少。

但从结构上讲,从同一段代码返回结果和计数是没有意义的。由于调用者必须能够遍历结果,因此确定计数是调用者应该负责的事情。每个调用者都应该能够处理明显的边界情况(即查询返回0行)而无需单独计数。每个调用者都应该能够遍历结果而无需知道将会有多少结果。每次我看到有人试图按照返回光标和计数的模式,正确的答案是重新设计程序并修复调用者提示设计的任何错误。