在WHERE子句中使用动态AND

时间:2014-03-20 09:49:42

标签: sql oracle plsql oracle11g oracle-sqldeveloper

DECLARE
   dynaCol  varchar2(200);
   varCol varchar2(100);

BEGIN

   dbms_output.put_line(dynaCol);
   select name into varCol from  GSSP_ETL.DEMO_TABLE_CHECK where ID='1'|| (SELECT q'$ and optional='N'$' NAME FROM DUAL) ;
   dbms_output.put_line(varCol);

END;

虽然我有一行id=1optional=N我仍然没有找到数据错误。

SELECT q'$ and optional='N'$' NAME FROM DUAL给了我and optional='N',所以这样使用没有错。

如果有人知道附加和在where子句中的原因或更好的方法,请提供帮助。

3 个答案:

答案 0 :(得分:0)

您的原始查询正在查找ID为“1且可选='N'”的行,这会导致问题。

如果要使用变量WHERE子句,则应使用动态SQL:

SQL> create table t (id, name, optional)
  2  as
  3  select 1, 'XXX','N' from dual
  4  /

SQL> select * from t;

        ID NAM O                                                                
---------- --- -                                                                
         1 XXX N                                                                


SQL> set serveroutput on
SQL> declare
  2   dynaCol  varchar2(200) := q'[ and optional='N']';
  3   varCol varchar2(100);
  4   p_id int := 1;
  5  begin
  6  
  7    execute immediate
  8    ' select name from t where id = :x '||dynaCol
  9    into varCol using p_id;
 10    dbms_output.put_line(varCol);
 11  end;
 12  /
XXX     

答案 1 :(得分:0)

很抱歉,由于声誉不佳,我无法评论。

不,我认为不可能立即做到,最好的方式就是德米特里所做的。 它可以动态发送整个select语句,但是一个不执行立即执行的部分..

答案 2 :(得分:0)

......你走近了。

由于您正在使用PL / SQL,为什么不考虑创建一个持久性对象,例如PL/SQL Stored Procedure? JBOSS端的代码将更少,数据库模式布局将进一步与您访问数据库时的代码分开。

演示表

这是对原始帖子的解释。这是我用来测试我的建议的表格。

 CREATE TABLE  "DEMO_TABLE_CHECK" 
    (     "ID" NUMBER(10,0) NOT NULL ENABLE, 
      "NAME" VARCHAR2(40) NOT NULL ENABLE, 
      "OPTIONAL" VARCHAR2(5) NOT NULL ENABLE, 
      CONSTRAINT "DEMO_TABLE_CHECK_PK" PRIMARY KEY ("ID") ENABLE
    )
 /

我的测试数据

Sample Data from DEMO_TABLE_CHECK

程序源代码

 CREATE or REPLACE PROCEDURE proc_example(p_id IN number, 
    p_opt IN varchar2 default null) 
 IS
    Result varchar2(100);

 BEGIN
    SELECT name
      INTO Result
      FROM GSSP_ETL.DEMO_TABLE_CHECK
     WHERE id = p_id
       AND optional = nvl(p_opt, optional); 

 dbms_output.put_line(Result);

 END proc_example;
  

请注意,此示例解决方案实际上取消了先前解决方案中提议的动态SQL调用。 PL / SQL过程代码的领域可能适用于推送和连接SQL命令的字符串。

示例调用和输出

 begin
 proc_example(p_id=> 1, p_opt=>'N');

 end;


 -- output:

 ALPHA



 begin
 proc_example(p_id=> 1, p_opt=> null);
 proc_example(p_id=> 1);

 end;

 -- output:

 ALPHA
 ALPHA

所有这些PL / SQL代码,最初位于从访问数据库的程序部分传递的块中,现在将驻留在数据库中。

PL / SQL程序设计的讨论

查询的可选部分(由p_opt表示)具有默认名称。这意味着如果该参数没有值,则该过程将忽略它并假设它等于定义的默认值。不会抛出任何错误。

 AND optional = nvl(p_opt, optional)

此行是附加SQL字符串的替代品。输入参数p_opt,无论是否提供(例如='N')或跳过(隐含于= null),SQL脚本都会根据提供的“切换”参数包含或排除此运算符的效果。

结束评论:

  

如果您希望基于最后一个动态SQL命令更好地区分结果,您可能希望尝试第一个条件实际上不明确的情况,例如ID列中的多个实例。 (如果ID = 1对于多个记录都是真的......)但是在这组结果中,第二个标准在与第一个结合时识别出一些独特的东西。