1

動的SQLを使用する必要がある場所を実装するロジックがあります(列名とWHERE句はその場で決定されます)。したがって、ここで私のカーソル(emp_ref_cursor)には動的SQLがあり、3つのカーソルフィールド(emp_id,emp_name,dept)があります。

句でこれらのカーソル フィールドを使用しWHEREて、ループ内で別の動的 SQL を実行しようとしています。Oracle はカーソル フィールドを識別できず、「ORA-00904:"EMP_REC"."EMP_ID": invalid identifier"ただしemp_rec.emp_idDBMS_OUTPUT.

注: コードの品質についてコメントしないでください。これは実際のコードではありません。これは単に問題を説明するために使用されます。コンプライアンス関連のものがあるため、実際のコードを投稿できません。

DECLARE
    emp_ref_cursor sys_refcursor; 
    v_sql varchar2(3900);

    TYPE emp_rec_type  IS RECORD (emp_id number,emp_name varchar2(100),dept_id varchar2(100)); 
    emp_rec emp_rec_type; 

    v_dept_id number:='1234';

    v_dob varchar2(100);
    v_desig varchar2(100);

    x_dynamic_col_1 varchar2(100):='dob'; --dynamic column(based on some condition)
    x_dynamic_col_2 varchar2(100):='designation'; --dynamic column(based on some condition)
    x_dynamic_col_3 varchar2(100):='emp_id'; --dynamic column(based on some condition)

BEGIN   
    v_sql:='SELECT emp_id,emp_name,dept FROM employee WHERE dept_id=' || v_dept_id;

    OPEN  emp_ref_cursor FOR  v_sql;
        LOOP
                FETCH emp_ref_cursor INTO  emp_rec;
                exit WHEN emp_ref_cursor%NOTFOUND;


                stmt:='SELECT ' || x_dynamic_col_1 || ',' || x_dynamic_col_2 || '
                      FROM employee A
                        WHERE emp_id=emp_rec.' || x_dynamic_col_3;

                DBMS_OUTPUT.PUT_LINE(stmt); 
                --Prints the SQL query as expected

                DBMS_OUTPUT.PUT_LINE('emp_rec.emp_id:'||emp_rec.emp_id);
                --Displays the value!!!

                execute immediate stmt into v_dob, v_desig; 
                --But why is it saying emp_rec.emp_id is invalid identifier??
    END LOOP;            
END;
4

2 に答える 2

2

emp_recローカル PL/SQL 変数として定義しました。PL/SQL データは、動的 SQL 実行のスコープにはありません。実行されると、ステートメントを実行しようとしたかのように、dbms_outputスタンドアロンによって別の SQL コンテキストで表示されるためです。そうすれば、それがemp_recクエリに存在しないことは明らかです。

それを参照すると、バインド変数を使用する必要があります。

WHERE emp_id=:dynamic_col_3';

そして、次のように実行します。

execute immediate stmt using emp_rec.emp_id;

ただし、句x_dynamic_col_3でローカル変数を使用することはできません。usingとにかく、この例では、別のテーブル列を使用するようにクエリを変更する必要があるため、動的レコード フィールドが変更されますが、それほど問題ではないようです。しかし、あなたはそのwhere条項もその場で変更されると言いました。その場合x、executin の前に関連するフィールドに設定する別のローカル変数を持つことができます。

于 2016-02-11T21:53:57.807 に答える
1

の使い方が間違っていEXECUTE IMMEDIATEます。INTOSQLクエリに句を入れる必要はありません。代わりにこれを使用してください:

            stmt:='SELECT ' || x_dynamic_col_1 || ',' || x_dynamic_col_2 || '
                     FROM employee A
                    WHERE emp_id=emp_rec.' || x_dynamic_col_3;

            execute immediate stmt into v_dob, v_desig; 
于 2016-02-11T22:06:17.067 に答える