如何获取sysref游标选择的记录总数?

时间:2017-01-12 19:12:25

标签: oracle plsql sys-refcursor oracle-cursor

背景

我正在开发一个调用PLSQL存储过程来检索和操作信息的Web应用程序。在一个这样的情况下,数据库有两个存储过程;一个选择给定参数集的记录总数,另一个返回具有相同参数的实际记录,加上分页参数(最小和最大rownum)。

EX(不是实际代码):

PROCEDURE get_records_count(
    p_first_name IN record_table.first_name%TYPE,
    p_last_name IN record_table.last_name%TYPE,
    p_resultCursor OUT sys_refcursor
)
IS BEGIN 
    OPEN p_resultCursor FOR 
    SELECT count(*) from record_table 
        WHERE first_name LIKE (p_first_name || '%') 
        OR last_name LIKE (p_last_name || '%');
END;


PROCEDURE get_records(
    p_first_name IN record_table.first_name%TYPE,
    p_last_name IN record_table.last_name%TYPE,
    p_min IN NUMBER,
    p_max IN NUMBER,
    p_resultCursor OUT sys_refcursor
)
IS BEGIN 
    OPEN p_resultCursor FOR 
    SELECT * from record_table 
        WHERE first_name LIKE (p_first_name || '%') 
        OR last_name LIKE (p_last_name || '%')
        AND rownum >= p_min AND rownum <= p_max;
END;

是否认为这是一个好主意超出了我的职位范围。问题是,无论何时更改任何存储过程,结果都不匹配。短期修复是查看两个存储过程,确定哪个选择标准适合哪个存储过程,然后编辑其他存储过程以使它们都匹配。

作为一个长期修复,我想更改get_records_count过程以调用get_records过程,然后返回将从结果sys_refcursor返回的记录总数。

EX:

PROCEDURE get_records_count(
    p_first_name IN record_table.first_name%TYPE,
    p_last_name IN record_table.last_name%TYPE,
    p_resultCursor OUT sys_refcursor
)
AS
v_recordsSelectedCursor sys_refcursor; 
BEGIN 
    /*I understand that I will need to change some logic in get_records to
      handle the case in which p_max is set to zero. 
      It should take this case to not apply an upper limit.*/ 
    get_records(p_first_name,p_last_name,0,0,v_recordsSelectedCursor);
    /*This is where I really have NO idea what I'm doing.
      Hopefully, you can infer what I'm trying to do. */ 
    OPEN p_resultCursor FOR
        SELECT count(*) FROM v_recordsSelectedCursor;  
END;

实际问题

如何选择将为sys_refcursor返回的记录数?结果数需要在sys_refcursor

中返回

2 个答案:

答案 0 :(得分:2)

游标只是一个用于获取行的规范 - 在获取所有行之前,它不知道将返回多少行。

任何涉及调用两次的方法都有可能导致结果不一致,除非您在过程开始时使用dbms_flashback.enable_at_time(并在结束时禁用它)。当然还有性能开销。

让游标包含其总行数的唯一方法是在count(*) over ()列表中包含分析select表达式。

答案 1 :(得分:1)

  

如何选择将为其返回的记录数   SYS_REFCURSOR?结果数字需要在a内返回   SYS_REFCURSOR。

您可以按照以下步骤修改您的程序:

PROCEDURE get_records_count(
    p_first_name IN record_table.first_name%TYPE,
    p_last_name IN record_table.last_name%TYPE,
    p_resultCursor OUT sys_refcursor
)
AS
v_recordsSelectedCursor sys_refcursor; 
type y is table of record_table%rowtype;
z y; 
num number:=0;
BEGIN 

    get_records(p_first_name,p_last_name,0,0,v_recordsSelectedCursor);

    fetch  v_recordsSelectedCursor bulk collect into z;

    ---taking the count of refcursor
    num:=z.count;

    OPEN p_resultCursor FOR
    select num from dual;         
    dbms_output.put_line(num);

END;

参见演示:

 SQL> SELECT count(*)
     FROM emp;

     COUNT(*)
     ----------
      14

SQL> CREATE OR REPLACE PROCEDURE sys_ref_rec_cnt (var OUT sys_refcursor)
  2  AS
  3  BEGIN
  4  OPEN var FOR
  5  SELECT *
  6    FROM emp;
  7  END;
  8  /

Procedure created.    

 SQL> DECLARE
  2  x     sys_refcursor;
  3  k     sys_refcursor;
  4  TYPE y IS TABLE OF emp%ROWTYPE;
  5  z      y;
  6  num   NUMBER        := 0;
  7  BEGIN
  8  sys_ref_rec_cnt (x);
  9  
 10  FETCH x
 11  BULK COLLECT INTO z;
 12  
 13  num :=z.count;
 14  
 15  open k for
 16   select num from dual;
 17   
 18  DBMS_OUTPUT.put_line ('No. Of records-->'||num);
 19  END;
 20  /

No. Of records-->14

PL/SQL procedure successfully completed.