Oracle:带有IN子句的Paramterized Query返回null值

时间:2015-12-28 16:35:25

标签: mysql oracle plsql plsqldeveloper

带有IN子句的Paramterized Query不起作用;它无法替换值

PROCEDURE p_getdata(A IN LONG,B IN LONG,C IN LONG, cur OUT c_data)
AS
l_query LONG;

   BEGIN
 IF C IS NULL THEN
open cur for  'select firstname, lastname, streetname, city
               from mytable 
               where zip IN(:A) AND streetnumber IN(:B) AND apt_num in(:C)' using A, B,C;

 END IF;
END;

这里

       a ='202020';
        b='12','13','10','92','02','02'
        c='A','B'

在Db中,所有数据类型都是varchar2。如何让它运行并存储值是游标?

3 个答案:

答案 0 :(得分:2)

您可以将逗号分隔列表作为参数(绑定变量)传​​递,但您负责在子查询中解析它。基于this thread的解决方案使用regexp_substr。

CREATE or REPLACE PROCEDURE p_getdata(A IN VARCHaR2, cur OUT sys_refcursor)
AS
BEGIN
open cur for  'with t1 as (select :A col from dual),
     t2 as (select level lvl,to_number(regexp_substr(col,''[^,]+'', 1, level)) col 
              from t1 connect by regexp_substr(col, ''[^,]+'', 1, level) is not null)
select col as id from t2' using A;
END;
/

程序简化了,但应该让人感觉如何使用它。

使用动态SQL(字符串连接)的一大优势是您无需在每次执行时解析语句。更不用说安全性(SQL注入的恐慌)。

用法:

DECLARE 
  l_cur SYS_REFCURSOR;
  l_id NUMBER;
BEGIN 
  p_getdata('1,1000,282828,4',l_cur);
 LOOP
    FETCH l_cur INTO l_id ;
    EXIT WHEN l_cur%NOTFOUND;
    dbms_output.put_line(l_id);
 END LOOP;
END;
/


1
1000
282828
4

<强>更新

上面的过程是简化的,为了获得你的功能,你应该在CURSOR中使用这样的查询(即首先使用子查询因子分割所有三个参数,而不是在查询中应用结果)

CREATE or REPLACE PROCEDURE p_getdata(A IN VARCHAR2, B in VARCHAR2, c in VARCHAR2, cur OUT sys_refcursor)
AS
BEGIN
open cur for  'with ta1 as (select :A col from dual),
     ta2 as (select level lvl,to_number(regexp_substr(col,''[^,]+'', 1, level)) col 
              from ta1 connect by regexp_substr(col, ''[^,]+'', 1, level) is not null),
 tb1 as (select :B col from dual),
     tb2 as (select level lvl,to_number(regexp_substr(col,''[^,]+'', 1, level)) col 
              from tb1 connect by regexp_substr(col, ''[^,]+'', 1, level) is not null),
 tc1 as (select :C col from dual),
     tc2 as (select level lvl,to_number(regexp_substr(col,''[^,]+'', 1, level)) col 
              from tc1 connect by regexp_substr(col, ''[^,]+'', 1, level) is not null)              
select firstname, lastname, streetname, city
from mytable 
where zip IN (select col from ta2) AND 
      streetnumber IN (select col from tb2) AND 
      apt_num in (select col from tc2)' using A, B, C;
END;
/

测试通过了

DECLARE 
  l_cur SYS_REFCURSOR;
  l_firstname VARCHAR2(20);
  l_lastname VARCHAR2(20);
  l_streetname VARCHAR2(20);
  l_city VARCHAR2(20);
BEGIN 
  p_getdata('1100,,1200','1,2','11,12' ,l_cur);
 LOOP
    FETCH l_cur INTO l_firstname, l_lastname, l_streetname, l_city;
    EXIT WHEN l_cur%NOTFOUND;
    dbms_output.put_line(l_firstname|| ' ' || l_lastname || ' ' || l_streetname  || ' ' || l_city);
 END LOOP;
END;
/

答案 1 :(得分:1)

使用参数的重点是使查询结构与查询数据分开。当你制作一个占位符时,你基本上承诺它只会代表一个值,而不是一个值列表。

在您的情况下,如果您信任您的数据,则您需要使用字符串连接并省略FIND_PACKAGE(Boost COMPONENTS python3)

USING

答案 2 :(得分:1)

open cur for  select firstname, lastname, streetname, city
           from mytable 
           where zip (SELECT REGEXP_SUBSTR(A,'[^,]+', 1, LEVEL)
  FROM DUAL
    CONNECT BY REGEXP_SUBSTR(A, '[^,]+', 1, LEVEL) IS NOT NULL
   AND streetnumber IN(SELECT REGEXP_SUBSTR(B,'[^,]+', 1, LEVEL)
  FROM DUAL
    CONNECT BY REGEXP_SUBSTR(B, '[^,]+', 1, LEVEL) IS NOT NULL
   AND apt_num in(SELECT REGEXP_SUBSTR(C,'[^,]+', 1, LEVEL)
  FROM DUAL
    CONNECT BY REGEXP_SUBSTR(C, '[^,]+', 1, LEVEL) IS NOT NULL



It is working