-1

バックグラウンド

PLSQL ストアド プロシージャを呼び出して情報を取得および操作する Web アプリケーションに取り組んでいます。そのような場合の 1 つは、データベースに 2 つのストアド プロシージャがあります。1 つは指定された一連のパラメーターのレコードの総数を選択するもので、もう 1 つは同じパラメーターとページネーション パラメーター (最小および最大 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 から返されるレコードの総数を返したいと考えています。

元:

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 内で返す必要があります

4

2 に答える 2

2

カーソルは、行をフェッチするための単なる仕様です。すべての行をフェッチするまで、返される行数はわかりません。

2 回呼び出す方法dbms_flashback.enable_at_timeは、手順の最初に使用しない限り (そして最後に無効にしない限り)、一貫性のない結果が得られるリスクがあります。もちろん、パフォーマンスのオーバーヘッドもあります。

カーソルにその合計行数を含める唯一の方法は、リストに分析count(*) over ()式を含めることです。select

于 2017-01-13T15:41:52.827 に答える
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.
于 2017-01-12T20:35:21.157 に答える