如何在动态sql查询中处理数组列表

时间:2017-05-15 07:05:56

标签: sql oracle dynamic plsql oracle10g

我想创建一个动态查询来处理数组列表。

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):PL / SQL:忽略语句错误(9,23):PLS-00306:错误   调用“||”

的参数的数量或类型

请帮忙

2 个答案:

答案 0 :(得分: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;

答案 1 :(得分:0)

您必须绑定参数p_class_array。在动态SQL中,您将使用冒号(:)作为前缀。如果您使用EXECUTE IMMEDIATEOPEN ... FOR,您将通过位置绑定参数以避免sql注入。

另请注意,在Select语句中,您正在执行*,因此在执行时您必须声明单个变量来保存结果。要避免错误,您必须在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.