2017-01-12 1 views
-1

CONTEXTEComment puis-je obtenir le nombre total d'enregistrements sélectionnés par un curseur sysref?

Je travaille sur une application web qui appelle les procédures stockées PLSQL pour récupérer et manipuler des informations. Dans un tel cas, la base de données a deux procédures stockées; celui qui sélectionne le nombre total d'enregistrements pour un ensemble donné de paramètres et un qui retourne les enregistrements réels avec les mêmes paramètres, plus les paramètres de pagination (min et max rownum).

EX (non le code réel):

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; 

Si oui ou non on pense que cela est une bonne idée est au-delà de la portée de ma position. Le problème est que chaque fois que la procédure stockée est modifiée, les résultats ne correspondent pas. Le correctif à court terme consiste à examiner les deux procédures stockées, à déterminer les critères de sélection à partir desquels la procédure stockée est appropriée, puis à modifier l'autre procédure stockée afin qu'elle corresponde. En tant que correctif à long terme, je voudrais modifier la procédure get_records_count pour appeler la procédure get_records, puis renvoyer le nombre total d'enregistrements qui seraient renvoyés par le sys_refcursor résultant.

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; 

QUESTION RÉEL

Comment puis-je choisir le nombre d'enregistrements qui seraient retournés pour un sys_refcursor? Le nombre obtenu doit être retourné dans un sys_refcursor

Répondre

2

Un curseur est juste une spécification pour récupérer les lignes - il ne sait pas combien de lignes va être renvoyé jusqu'à ce qu'il les ait tous récupérés. Toute méthode impliquant l'appel deux fois risque d'obtenir des résultats incohérents, sauf si vous utilisez dbms_flashback.enable_at_time au début de la procédure (et désactivez-le à la fin). Il y a aussi les frais généraux de performance, bien sûr. La seule façon d'obtenir un curseur pour inclure son nombre total de lignes est d'inclure une expression analytique count(*) over() dans la liste select.

1

Comment puis-je choisir le nombre d'enregistrements qui seraient retournés pour un sys_refcursor? Le nombre résultant doit être retourné dans un sys_refcursor.

Vous pouvez modifier votre procédure ci-dessous:

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; 

Voir la démo:

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

Cela aide un peu. Savez-vous s'il est possible d'obtenir la valeur de la sortie num dans un curseur sysref comme si je l'avais récupéré avec SELECT? –

+0

Le code ci-dessus fait la même chose. C'est mettre le compte à un refcursor – XING

+0

Oh ouais, n'avait pas remarqué cela. Merci beaucoup! –