9

私はOracle(10g.2)をPHPプログラマーとして3年近く使用していますが、課題を与えられたとき、refカーソルとコレクション型を初めて使用しようとしました。そして、問題に直面したときに Web を検索したところ、この ora-00932 エラーに本当に圧倒されました。古い手の助けが必要です。

これが私が取り組んできたことです。テーブルから行を選択して参照カーソルに入れ、レコードタイプを使用してそれらを連想配列内に集めたいと考えています。そして、この連想配列から、ref カーソルを作成します。理由は聞かないでください。より複雑な代入を行うために必要なため、このような複雑なコードを書いています。わかりにくいかもしれませんので、私のコードをお見せしましょう。

Toad の [タイプ] タブで 2 つのタイプを定義しています。それらの 1 つはオブジェクト型です。

CREATE OR REPLACE
TYPE R_TYPE AS OBJECT(sqn number,firstname VARCHAR2(30), lastname VARCHAR2(30));

もう 1 つは、上で作成したオブジェクト タイプを使用するコレクション タイプです。

CREATE OR REPLACE
TYPE tr_type AS TABLE OF r_type;

次に、パッケージを作成します。

CREATE OR REPLACE PACKAGE MYPACK_PKG IS
TYPE MY_REF_CURSOR IS REF CURSOR;
PROCEDURE MY_PROC(r_cursor OUT MY_REF_CURSOR);
END MYPACK_PKG;

パッケージ本体:

CREATE OR REPLACE PACKAGE BODY MYPACK_PKG AS
 PROCEDURE MY_PROC(r_cursor OUT MY_REF_CURSOR) AS
  rcur MYPACK_PKG.MY_REF_CURSOR;
  sql_stmt VARCHAR2(1000);
  l_rarray   tr_type := tr_type();
                l_rec r_type;

 BEGIN
     sql_stmt :=  'SELECT 1,e.first_name,e.last_name  FROM hr.employees e ';
     OPEN rcur FOR sql_stmt;
     LOOP
       fetch rcur into l_rec;
                  exit when rcur%notfound;
     l_rarray := tr_type( l_rec );
     END LOOP;
   CLOSE rcur;
    --OPEN r_cursor FOR SELECT * FROM TABLE(cast(l_rarray as tr_type) );


END MY_PROC;
END MYPACK_PKG;

refカーソルを開く最後の行をコメントアウトしました。Toad の SQL Editor でこの手順を実行すると別のエラーが発生するため、2 番目に質問します。最後に、Toad でコードを実行します。

variable r refcursor
declare
r_out MYPACK_PKG.MY_REF_CURSOR;
begin
MYPACK_PKG.MY_PROC(r_out);
:r := r_out;
end;
print :r

そこで ora-00932 エラーが発生します。

4

1 に答える 1

6

REFCURSORの使用方法は一般的ではありません。これは、それらを使用する標準的な方法です。

SQL> CREATE OR REPLACE PACKAGE BODY MYPACK_PKG AS
  2     PROCEDURE MY_PROC(r_cursor OUT MY_REF_CURSOR) AS
  3     BEGIN
  4        OPEN r_cursor FOR SELECT e.empno,e.ENAME,null  FROM scott.emp e;
  5     END MY_PROC;
  6  END MYPACK_PKG;
  7  /

Corps de package crÚÚ.

SQL> VARIABLE r REFCURSOR
SQL> BEGIN
  2     MYPACK_PKG.MY_PROC(:r);
  3  END;
  4  /

ProcÚdure PL/SQL terminÚe avec succÞs.

SQL> PRINT :r

     EMPNO ENAME      N
---------- ---------- -
      7369 SMITH
      7499 ALLEN
      7521 WARD
      7566 JONES
      7654 MARTIN
      [...]

14 ligne(s) sÚlectionnÚe(s).

ここで何を達成しようとしているのかわかりません。プロシージャ内でrefカーソルをフェッチしてから、同じデータを持つ別のrefカーソルを返します。プロシージャでカーソルをフェッチする必要はまったくないと思います。呼び出し元のアプリにフェッチを実行させます(ここでは、フェッチはによって実行されますprint)。

更新:なぜ役に立たないエラーメッセージが表示されるのですか?

動的に開いたカーソルを使用していますが、これが役に立たないエラーメッセージが表示される理由の1つだと思います。固定SQLを使用する場合、エラーメッセージは異なります。

SQL> CREATE OR REPLACE PACKAGE BODY MYPACK_PKG AS
  2     PROCEDURE MY_PROC(r_cursor OUT MY_REF_CURSOR) AS
  3        TYPE type_rec IS RECORD (qn number,
  4                                 firstname VARCHAR2(30),
  5                                 lastname VARCHAR2(30));
  6        lt_record type_rec; /* Record type */
  7        lt_object r_type; /* SQL Object type */
  8     BEGIN
  9        OPEN r_cursor FOR SELECT e.empno,e.ENAME,null  FROM scott.emp e;
 10        FETCH r_cursor INTO lt_record; /* This will work */
 11        FETCH r_cursor INTO lt_object; /* This won't work in 10.2 */
 12     END MY_PROC;
 13  END MYPACK_PKG;
 14  /

Package body created

SQL> VARIABLE r REFCURSOR
SQL> BEGIN
  2     MYPACK_PKG.MY_PROC(:r);
  3  END;
  4  /
BEGIN
*
ERREUR Ó la ligne 1 :
ORA-06504: PL/SQL: Return types of Result Set variables or query do not match
ORA-06512: at "APPS.MYPACK_PKG", line 11
ORA-06512: at line 2

現在10.2では、カーソルをPLSQLレコードにフェッチできますが、SQLオブジェクトにはフェッチできないことを概説しました。

更新::PLS-00306間違った数またはタイプの引数に関して

l_rarrayはネストされたテーブルです。要素を格納できるようにするには、初期化してから拡張する必要があります。例えば:

SQL> CREATE OR REPLACE PACKAGE BODY MYPACK_PKG AS
  2     PROCEDURE MY_PROC(r_cursor OUT MY_REF_CURSOR) AS
  3        lr_array tr_type := tr_type(); /* SQL Array */
  4     BEGIN
  5        FOR cc IN (SELECT e.empno, e.ENAME, NULL lastname
  6                     FROM scott.emp e) LOOP
  7           lr_array.extend;
  8           lr_array(lr_array.count) := r_type(cc.empno,
  9                                              cc.ename,
 10                                              cc.lastname);
 11           /* Here you can do additional procedural work on lr_array */
 12        END LOOP;
 13        /* then return the result set */
 14        OPEN r_cursor FOR SELECT * FROM TABLE (lr_array);
 15     END MY_PROC;
 16  END MYPACK_PKG;
 17  /

Corps de package crÚÚ.

SQL> print r

       SQN FIRSTNAME                      LASTNAME
---------- ------------------------------ -----------
      7369 SMITH                          
      7499 ALLEN                          
      7521 WARD                           
      [...]

14 ligne(s) sÚlectionnÚe(s).

詳細については、 PL/SQLコレクションおよびレコードのドキュメントを参照してください。

于 2011-01-04T10:58:16.820 に答える