2017-05-15 3 views
-1

배열 목록을 처리 할 동적 쿼리를 만들고 싶습니다. PL/SQL : 문 무시 오류 (9,23) :동적 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)을 제공 PLS-00306을 : 인수의 잘못 번호 또는 종류 '||'을 (를) 호출하십시오.

+0

있습니다 더 많은 조건을 그래서 sql이 동적으로 사용되기를 원합니다. – user2190186

답변

0

당신은 콜론 (:)로 접두사 것 매개 변수 p_class_array .IN 동적 SQL을 결합해야합니다 도와주세요. EXECUTE IMMEDIATE 또는 OPEN ... FOR을 사용하면 SQL 삽입을 피하기 위해 위치를 통해 매개 변수를 바인딩합니다.

Select 명세서에서 *을 수행 중이므로 실행 중에 결과를 보관할 개별 변수를 선언해야합니다. 아래 그림과 같이 실수를 aviod하려면 SELECT 문에서 열 이름을 선언해야합니다 :

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 AND 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을 사용하여 (SELECT * FROM TABLE (p_class_array)) 성능 문제. – MT0