【问题标题】:How to build the query dynamically如何动态构建查询
【发布时间】:2012-12-31 21:39:03
【问题描述】:

我正在创建这样的查询:

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)) 这样条件就失效了

【问题讨论】:

  • null is null是否不用检查。
  • 我需要检查bcos它是一个可选参数。目前它在表中的检查空间
  • 不,你不明白。无需将 null is null 作为任何 where 子句的一部分。如果p_supp_nbr is null,则不要包含where 子句的那部分。
  • 如果我不包括当用户没有在参数中输入任何内容时,我需要忽略该条件。如果我检查 supplr_Vvn=NULL 那么它是错误的。所以这个条件是必需的
  • 0_0 嗯...你永远都不想检查任何东西是否等于 null。 Null 不是一个值。只需根据您的哪些参数(如果有)恰好是 null 来更改 where 子句。

标签: sql oracle dynamic plsql plsqldeveloper


【解决方案1】:

试试这个:

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')||'''))

【讨论】:

  • 在上述查询中,当 p_supp_nbr 为 NULL 时,其检查 ' ' 为 NULL。所以空间不为 NULL 对
【解决方案2】:

不要那样做!您冒着 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 时就知道值是否为 null,您可以改为这样做:

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;

【讨论】:

  • 我最喜欢第二个!但是if 语句的第一部分不是多余的吗?这行不通:IF p_supp_nbr IS NOT NULL THEN v_sql := v_sql || ' AND supplr_vn = :p_supp_nbr'; END IF;
  • @glh 我应该在我的回答中解释:是的,这在逻辑上是多余的,但是 Native Dynamic SQL 仅在绑定变量的数量固定时才有效,因此我们需要在查询中引用 :p_supp_nbr 是否我们是否使用它。
【解决方案3】:

一般 Oracle 示例:

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;
/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-23
    • 2012-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多