我有一个过程,它返回ref游标作为输出参数。我需要找到一种方法来获得光标中记录数。目前,我通过重复相同的选择查询获取了计数,这阻碍了性能。
例如:
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游标中的行数获取到vCount中。
谢谢!
Oracle通常不知道将从游标中提取多少行,直到最后一次提取找不到要返回的行为止。由于Oracle不知道将返回多少行,因此在不获取所有行的情况下(就像您在重新运行查询时所做的那样),您也不能这样做。
除非使用单用户系统或使用非默认事务隔离级别(这会带来额外的复杂性),否则无法保证光标将返回的行数与第二个查询返回的count(*)
匹配。完全有可能是另一个会话在您打开光标和运行count(*)
之间提交了更改。
如果您真的决定要生成准确的计数,那么可以在用于打开光标的查询中添加一个定义为count(*) over ()
的cnt
列。然后,光标中的每一行都将有一个列cnt
,它将告诉您将返回的行总数。Oracle需要做更多的工作来生成cnt
,但这比两次运行同一查询要少。
不过,从体系结构上讲,从同一段代码返回结果和计数是没有意义的。确定计数是调用者应该负责的事情,因为调用者必须能够遍历结果。每个调用方都应该能够处理明显的边界情况(即查询返回0行),而不需要单独的计数。每个调用方都应该能够迭代结果,而不需要知道会有多少结果。每次我看到有人试图遵循返回光标和计数的模式时,正确的答案都是重新设计过程,并修复调用方上提示设计的任何错误。