2017-01-12 31 views
-1

背景如何獲取由sysref遊標選擇的記錄總數?

我正在調用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

遊標是隻爲獲取行一個規範 - 它不知道有多少行直到將它們全部取出爲止。

任何涉及調用兩次方法風險得到不一致的結果,除非你用dbms_flashback.enable_at_time在程序的開始(和結束時禁用它)。當然,還有性能開銷。

獲得遊標以包括其總行數的唯一方法是在select列表中包含分析count(*) over()表達式。

1

如何選擇將返回 sys_refcursor的記錄數?結果編號需要在 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. 
+0

這會有所幫助。你知道是否有可能將num輸出的值放入sysref遊標中,就像我用SELECT檢索過的一樣? –

+0

上面的代碼是這樣做的。這是計數到refcursor – XING

+0

噢,沒有注意到這一點。萬分感謝! –