2017-05-15 15 views
-1

配列リストを処理する動的クエリを作成します。 PL/SQL:ステートメントは無視エラー(9,23):PLS-00306:間違った 数またはで引数の型動的SQLクエリで配列リストを処理する方法

create or replace TYPE p_type IS table of varchar2(4000) ; 

CREATE OR REPLACE PROCEDURE test_proc_sk(
    p_class_array IN p_type, 
    p_emp_record OUT SYS_REFCURSOR) 
IS 
    lv_stmt VARCHAR2(100); 
BEGIN 
    lv_stmt   := 'Select * from dept where deptno = 10 '; 
    IF(p_class_array IS NOT NULL) THEN 
    lv_stmt  := lv_stmt || 'AND dname IN (select column_value from table(' || p_class_array ||'))'; 
    END IF; 
    dbms_output.put_line(lv_stmt); 
    OPEN p_emp_record FOR lv_stmt; 
END; 

それは、コンパイルエラー

エラー(9,5)を与えます'||'を呼び出す

あなたはコロン(:)でそれらの接頭辞うパラメータp_class_array .IN、動的SQLをバインドする必要があります

+0

より多くの条件がありますので、私は、 SQLを動的に使用します。 – user2190186

答えて

0

を助けてください。 EXECUTE IMMEDIATEまたはOPEN ... FORを使用する場合は、SQLインジェクションを避けるために、位置を介してパラメータをバインドします。

Selectステートメントでは*を実行しているので、実行中は結果を保持するために個々の変数を宣言する必要があります。以下に示すように、あなたがselect文で列名を宣言する必要があります間違いをaviodするには:

CREATE OR REPLACE PROCEDURE test_proc_sk(
    p_class_array IN p_type, 
    p_emp_record OUT SYS_REFCURSOR) 
IS 
    lv_stmt VARCHAR2(200); 
BEGIN 
    lv_stmt   := 'Select deptno,dname from dept where deptno = 10 '; 
    IF(p_class_array.count > 0) THEN 
    lv_stmt  := lv_stmt || ' AND dname IN (select column_value from table(:p_class_array))';  
    END IF; 
    dbms_output.put_line(lv_stmt); 
    OPEN p_emp_record FOR lv_stmt using p_class_array; 
END; 

/

実行:

SQL> Select * from dept ; 

SQL>/

    DEPTNO DNAME 
---------- ---------------------------------------------------------------------------------------------------- 
     10 CTS 
     20 WIPRO 
     30 TCS 

SQL> DECLARE 
    vr p_type:= p_type(); 
    x SYS_REFCURSOR; 
    z VARCHAR2(10); 
    z1 number; 
BEGIN 
    vr.extend(2); 
    vr (1) := 'CTS'; 
    vr (2) := 'TCS'; 
     test_proc_sk (vr, x); 

    LOOP 
     FETCH x INTO z1,z; 

     EXIT WHEN x%NOTFOUND; 
     DBMS_OUTPUT.PUT_LINE (z ||' ' ||z1); 
    END LOOP; 
END; 
/
SQL>/
Select deptno,dname from dept where deptno = 10 AND dname IN (select column_value from table(:p_class_array)) 
CTS 10 

PL/SQL procedure successfully completed. 
+0

すべての列を選択したいと思います。私は、deptno = 10とdname IN(テーブル(:p_class_array)からcolumn_valueを選択)のどこからSelect dnameとしてsqlクエリを取得しています。バインド変数 – user2190186

+0

を使用していない場合は、 'DEPT'テーブルの型を作成してオブジェクトにするか、またはPLSQLでテーブルの型の変数を宣言する必要があります。 – XING

+0

'varchar変数のデータを選択します.' OPは' varchar'変数にデータを選択しません。 'lv_stmt'' varchar'変数に 'select'文が含まれています。 OPは単純にvarcharとネストしたテーブルを連結しようとしているので、エラーです。 –

1

MEMBER OF operatorを使用します。

CREATE OR REPLACE PROCEDURE test_proc_sk(
    p_class_array IN p_type, 
    p_emp_record OUT SYS_REFCURSOR 
) 
IS 
BEGIN 
    OPEN p_emp_record FOR 
    SELECT * 
    FROM dept 
    WHERE deptno = 10 
    AND (p_class_array IS EMPTY OR dname MEMBER OF p_class_array); 
END; 
+0

最近、私は 'select from table()'の代わりに 'member'を使用しましたが、メンバーは非常に遅い – Mottor

+0

@Mottor(OR * dname IN(SELECT * FROM TABLE(p_class_array)) 'パフォーマンスの問題。 – MT0

関連する問題