如何构建查询动态

问题描述:

我创建一个这样的查询:如何构建查询动态

v_sql:=' SELECT abc FROM '||v_table||' 
     WHERE area IN ('''||v_area||''') 
      AND (
       ('''||p_supp_nbr||''' IS NULL) 
       OR 
       supplr_vn IN ('''||p_supp_nbr||''') 
       ) 

现在当p_supp_nbrNULL那么它不采取。

我得到这样的:

((''IS NULL) OR (supplr_vn =''))

在表格中的检查空间

,但我想((NULL IS NULL) OR (supplr_vn =NULL))使病情bcomes无效

+1

不需要检查'null是否为null'。 – 2013-01-17 11:04:15

+0

我将需要检查bcos它是一个可选参数。目前它的检查空间在表 – Satheesh

+0

不,你不明白。没有必要在任何'where'子句中包含null作为null的一部分。如果'p_supp_nbr为null',则不要包含'where'子句的那部分。 – 2013-01-17 11:10:01

试试这个:

v_sql:=' SELECT abc FROM '||v_table||' 
WHERE area IN ('''||v_area||''') 
    AND (('''||p_supp_nbr||''' IS NULL) 
    OR supplr_vn IN ('''||NVL(p_supp_nbr, 'NULL')||''')) 
+0

在上面的查询中,当p_supp_nbr为NULL时,那么它的检查''是NULL.so空格不是NULL right – Satheesh

不要做在!您冒着SQL注入问题的风险。使用绑定变量:

v_sql:= 'SELECT abc FROM '||v_table|| 
     ' WHERE area = :v_area 
      AND (
       :p_supp_nbr IS NULL 
       OR 
       supplr_vn = :p_supp_nbr 
       ) 

当然,因为你知道在生成的动态SQL是否值点为空,你可以不是这样做:

v_sql:= 'SELECT abc FROM '||v_table||' 
     WHERE area = :v_area'; 
IF p_supp_nbr IS NULL THEN 
    v_sql := v_sql || ' AND :p_supp_nbr IS NULL'; 
ELSE 
    v_sql := v_sql || ' AND supplr_vn = :p_supp_nbr'; 
END IF; 

无论哪种方式,那么你就可以绑定值在这样运行:

OPEN my_refcursor FOR v_sql USING v_area, p_supp_nbr; 
+0

我最喜欢第二个!但是,“if”陈述的第一部分不是多余的?这不会工作:'如果p_supp_nbr不是NULL,则v_sql:= v_sql || 'AND supplr_vn =:p_supp_nbr'; END IF;' – glh

+2

@glh我应该在我的回答中解释:是的,它在逻辑上是多余的,但Native Dynamic SQL只适用于绑定变量的数量是固定的,所以我们需要在查询中引用:p_supp_nbr是否使用它或不。 –

一般甲骨文例如:

DECLARE 
    v_sql1  VARCHAR2(200); 
    v_sql2  VARCHAR2(200); 
    v_tab_name VARCHAR2(200):= 'scott.emp'; 
    v_listCol  VARCHAR2(200):= 'job'; 
    v_list  VARCHAR2(200):= '''MANAGER'', ''CLERK'''; 
-- 
    v_colName  VARCHAR2(200):= 'comm'; 
    v_comm  NUMBER:= 1400; 
BEGIN 
    v_sql1:= 'SELECT * FROM '|| v_tab_name ||' WHERE '||v_listCol ||' IN (:v)'; 
    v_sql2:= 'SELECT * FROM '|| v_tab_name ||' WHERE ('||v_colName ||' = :v OR '||v_colName ||' IS NULL)'; 
-- 
    EXECUTE IMMEDIATE v_sql1 USING v_list; 
    dbms_output.put_line(v_sql1); 
-- 
    EXECUTE IMMEDIATE v_sql2 USING v_comm; 
    dbms_output.put_line(v_sql2); 
END; 
/