3

動的SQLステートメントで強力な参照curを使用しようとしていますが、エラーが発生していますが、弱いカーソルを使用すると機能します。理由を説明し、方法に関する問題を含むOracleサーバーアーキテクトのリンクを転送してくださいコンパイルと解析は Oracle サーバーで行われます。これはコードとともにエラーです。

ERROR at line 6:
ORA-06550: line 6, column 7:
PLS-00455: cursor 'EMP_REF_CUR' cannot be used in dynamic SQL OPEN statement
ORA-06550: line 6, column 2:
PL/SQL: Statement ignored

declare
      type ref_cur_type IS REF CURSOR RETURN employees%ROWTYPE; --Creating a strong REF cursor,employees is a table
     emp_ref_cur ref_cur_type;
     emp_rec employees%ROWTYPE;
BEGIN      
   OPEN emp_ref_cur FOR 'SELECT * FROM employees';
           LOOP
                   FETCH emp_ref_cur INTO emp_rec;
                   EXIT WHEN emp_ref_cur%NOTFOUND;
           END lOOP;       
END;
4

3 に答える 3

9

厳密に型指定された ref カーソルを使用するプロシージャを次に示します。

SQL> create or replace procedure p1 is
  2      type dept_rc is ref cursor return dept%rowtype;
  3      my_ref_cursor dept_rc;
  4  begin
  5      open my_ref_cursor for
  6          select * from dept;
  7  end;
  8  /

Procedure created.

SQL>

EMP レコードの署名が DEPT テーブルの署名と一致しないため、この次のステートメントは失敗します。

SQL> create or replace procedure p1 is
  2      type dept_rc is ref cursor return dept%rowtype;
  3      my_ref_cursor dept_rc;
  4  begin
  5      open my_ref_cursor for
  6          select * from emp;
  7  end;
  8  /

Warning: Procedure created with compilation errors.

SQL> show error
Errors for PROCEDURE P1:

LINE/COL ERROR
-------- -----------------------------------------------------------------
5/5      PL/SQL: SQL Statement ignored
6/9      PLS-00382: expression is of wrong type

SQL>

しかし、射影を DEPT テーブルに一致するように変更すると、再び成功します。

SQL> create or replace procedure p1 is
  2      type dept_rc is ref cursor return dept%rowtype;
  3      my_ref_cursor dept_rc;
  4  begin
  5      open my_ref_cursor for
  6          select deptno, ename, job from emp;
  7  end;
  8  /

Procedure created.

SQL>

では、動的 SQL で厳密に型指定された ref-cursor を使用できないのはなぜでしょうか?

SQL> create or replace procedure p1 is
  2      type dept_rc is ref cursor return dept%rowtype;
  3      my_ref_cursor dept_rc;
  4  begin
  5      open my_ref_cursor for
  6          'select * from dept';
  7  end;
  8  /

Warning: Procedure created with compilation errors.

SQL> show error
Errors for PROCEDURE P1:

LINE/COL ERROR
-------- -----------------------------------------------------------------
5/5      PL/SQL: Statement ignored
5/10     PLS-00455: cursor 'MY_REF_CURSOR' cannot be used in dynamic SQL
         OPEN statement

SQL>

コンパイラは動的 SQL ステートメント内の文字列を解析できないためです。そのため、クエリのプロジェクション内の列の数とデータ型が ref カーソルのシグネチャと一致するとは断言できません。したがって、ref カーソル変数とクエリの間のコントラクトを検証できません。USER_TAB_COLUMNS に対するクエリから動的 SQL ステートメントを組み立てることができると考えると、なぜこれが許可されないのかを理解するのはさらに簡単です。

于 2010-05-06T19:21:20.187 に答える
1

もう 1 つの可能性は、Record Type オブジェクトを宣言して定義し、クエリ結果のコンテナーにすることです。これは、クエリが JOIN クエリであり、複数の結合されたテーブルから列を返す場合に役立ちます。

SQL> create or replace procedure p1 is
     /* Declare you destination data structure row container */
     TYPE TestRecTyp IS RECORD (
        deptno varchar(50),
        ename  varchar(50),
        job    varchar(50)
     );
     /* Define an instance of the record type */
     testrec TestRecTyp;

     type dept_rc is ref cursor; /*return dept%rowtype;*/
     my_ref_cursor dept_rc;
     begin
         open my_ref_cursor for 'select deptno,ename,job from emp';
         LOOP
             FETCH my_ref_cursor INTO testrec;
         EXIT WHEN my_ref_cursor%NOTFOUND;

             /* Do some operations with testrec*/

         END LOOP;
     end;

注: 'select deptno,ename,job from emp' を v_sql などの変数に置き換え、この変数をプロシージャ本体内の SQL ステートメントで更新することにより、動的に構築された SQL クエリ ステートメントで上記の手法を使用できます。

于 2013-01-22T22:32:02.247 に答える