2009-06-17 12 views
2

数値nをとり、指定されたクエリの最初のn個の結果を返して、それらのn個の行を排他的にロックするストアドプロシージャを作成しようとしています。私はSQLに少し慣れていますし、データ型を正しく照合するのが少し難しいです。私はそのようにように、プロシージャ本体内でカーソルを定義弱く定義された参照カーソルを定義する際に問題が発生しました

PACKAGE package IS 
    Type out_result_type is REF CURSOR; 
    PROCEDURE stored_proc 
    (in_n IN NUMBER DEFAULT 10, 
     out_list IN OUT out_result_type); 

CURSOR OUT_RESULT_TYPE IS 
     SELECT a.id 
      FROM schema.table a 
      WHERE (some conditions) AND rownum <= in_n; 

少し後に、私は、その後の結果を抽出しよう

マイパッケージ仕様は次のようになります出力変数へのカーソル:

OPEN OUT_RESULT_TYPE; 
FETCH OUT_RESULT_TYPE INTO out_list; -- error on this line 
CLOSE OUT_RESULT_TYPE; 

しかし、このコードはコンパイルされていません。 oracleはout_listがすでに競合するデータ型で定義されていると不平を言っています。どのように私はこの問題を解決することができますか?それは私を夢中にさせている!

ありがとうございます。

答えて

1
CREATE OR REPLACE PACKAGE pkg_test 
AS 
     TYPE tt_cur IS REF CURSOR; 
     PROCEDURE prc_cur (retval OUT tt_cur); 
END; 

CREATE OR REPLACE PACKAGE BODY pkg_test 
AS 
     PROCEDURE prc_cur (retval OUT tt_cur) 
     AS 
     BEGIN 
       OPEN retval 
       FOR 
       SELECT * 
       FROM dual; 
     END; 
END; 

ロックしたい場合は、使用:

CREATE OR REPLACE PACKAGE BODY pkg_test 
AS 
     PROCEDURE prc_cur (retval OUT tt_cur) 
     AS 
     BEGIN 
       OPEN retval 
       FOR 
       SELECT a.id 
       FROM schema.table a 
       WHERE (some conditions) 
         AND rownum <= in_n 
       ORDER BY 
         column 
       -- Never forget ORDER BY! 
       FOR UPDATE; 
     END; 
END; 
+0

なぜsys_refcursorを使用しないのですか? – tuinstoel

+0

@tuinstoel:私はいつもそれが存在することを忘れる:) – Quassnoi

+0

ありがとう、これは非常に有用だった –

0

あなたout_listが間違った型でなければなりません。 (スクリプトが10.2.0.3上で実行)考えてみましょう:

CREATE TABLE t AS SELECT ROWNUM ID FROM all_objects WHERE ROWNUM <= 100; 

CREATE OR REPLACE PACKAGE cursor_pck AS 
    TYPE out_result_type is REF CURSOR; 
    PROCEDURE stored_proc (p_in IN NUMBER DEFAULT 10, 
          p_out_list IN OUT out_result_type); 
END cursor_pck; 
/

あなたがFOR UPDATE句を使用するのと同じ時間に行を選択してロックしたい場合は、次の設定で

CREATE OR REPLACE PACKAGE BODY cursor_pck AS 
    PROCEDURE stored_proc (p_in IN NUMBER DEFAULT 10, 
          p_out_list IN OUT out_result_type) IS 
    BEGIN 
     OPEN p_out_list FOR SELECT a.id FROM t a WHERE ROWNUM <= p_in FOR UPDATE; 
    END stored_proc; 
END cursor_pck; 
/

を、あなたは

SQL> SET SERVEROUTPUT ON; 
SQL> DECLARE 
    2  l_cursor cursor_pck.out_result_type; 
    3  l_id t.id%TYPE; 
    4 BEGIN 
    5  cursor_pck.stored_proc(3, l_cursor); 
    6  LOOP 
    7  FETCH l_cursor INTO l_id; 
    8  EXIT WHEN l_cursor%NOTFOUND; 
    9  dbms_output.put_line(l_id); 
10  END LOOP; 
11 END; 
12/

1 
2 
3 

PL/SQL procedure successfully completed 
0

二つの発言:

    次のようにプロシージャを呼び出します。
  1. カーソルがロックされません。
  2. Type out_result_type is REF CURSOR;を実行する必要はありません。デフォルトのタイプsys_refcursorを使用してください。ここを参照してください:これは、それが書かれているように動作するつもりはないOracle - How to have an out ref cursor parameter in a stored procedure?
0

  1. out_listはカーソルではなく、カーソルの結果を期待しているため。
  2. out_result_typeはすでにタイプのために使用されているので、あなたは、同じスコープ内カーソルようにそれを再定義することはできません。
0

Oracleには事前定義された弱参照カーソルsys_refcursorが用意されています。使用方法は次のようになります。

CREATE OR REPLACE PACKAGE pkg_test 
AS 
    PROCEDURE prc_cur (p_retval OUT sys_refcursor, 
         p_lookup IN VARCHAR2); 
END pkg_test; 


CREATE OR REPLACE PACKAGE BODY pkg_test 
AS 
    PROCEDURE prc_cur(p_retval OUT sys_refcursor 
         p_lookup IN VARCHAR2) 
    IS 
    BEGIN 
     OPEN retval FOR SELECT a.value 
          FROM tblname a 
         WHERE a.id <= p_lookup; 
    END prc_cur; 
END pkg_test; 

これにより、型を宣言する必要がありません。 sys_refcursorは、開いているカーソルからの結果セットへのポインタです。 Javaに慣れている場合は、クエリーの結果を取得する方法を提供するjava.sql.ResultSetオブジェクトと同じ概念です。

関連する問題