在我的项目中有一个冗长的动态查询,如下所示 -
basic_query varchar2(1000);
final_query varchar2(1500);
where_clause varchar2(500) default null;
basic_query :=<select ...from table where ....>
If(<condition1>)
then
where_clause := <one_new_condition_will_be_added_in_where_clause1>
elsif(<condition2>)
then
where_clause := <one_new_condition_will_be_added_in_where_clause2>
elsif(<condition3>)
then
where_clause := <one_new_condition_will_be_added_in_where_clause3>
else
where_clause := <one_new_condition_will_be_added_in_where_clause4>
endif;
final_query :=basic_query || where_clause || '<group_by_clause'> || <'order_by_clause'>;
execute immediate final_query;
现在我的客户想要将此动态查询转换为静态查询。我尝试使用CASE,但它无法正常工作。
select ...from table where condition1,and
case(
when(<condition1> and <one_new_condition_will_be_added_in_where_clause1>)
then 'valid'
when(<condition2> and <one_new_condition_will_be_added_in_where_clause2>
then 'valid'
when(<condition1> and <one_new_condition_will_be_added_in_where_clause3>)
then 'valid'
when(<condition2> and <one_new_condition_will_be_added_in_where_clause4>
then 'valid'
else 'invalid'
end;)='valid
检查CASE条款中给出的条件&amp;如果任何一个为真,则在没有在where子句中添加这些条件的情况下给出输出。
希望有人能理解这个问题&amp;会给出解决方案。 在此先感谢。
答案 0 :(得分:1)
正如我在评论中所说,原则上使用case
,如你所示,应该工作(在'工作'我的意思是产生相同的结果;这并不一定意味着它更好,可能有性能和维护的影响等)。为了演示我将创建一些虚拟数据:
create table t42 (flag varchar2(1), value varchar2(10), cond number);
insert into t42 values ('Y', 'One', 1);
insert into t42 values ('Y', 'Two', 2);
insert into t42 values ('Y', 'Three', 3);
...并且包中有两个程序:
create package p42 as
procedure proc1(parm number);
procedure proc2(parm number);
end p42;
/
create package body p42 as
procedure proc1(parm number) is
basic_query varchar2(1000);
final_query varchar2(1500);
where_clause varchar2(500) default null;
result t42.value%type;
begin
basic_query := 'select value from t42 where flag = ''Y'' ';
if parm = 2013 then
where_clause := 'and cond = 1 ';
elsif parm = 2012 then
where_clause := 'and cond = 2 ';
else
where_clause := 'and cond = 3 ';
end if;
final_query := basic_query || where_clause;
execute immediate final_query into result;
dbms_output.put_line(result);
end proc1;
procedure proc2(parm number) is
result t42.value%type;
begin
select value into result from t42 where flag = 'Y'
and case
when parm = 2013 and cond = 1 then 'valid'
when parm = 2012 and cond = 2 then 'valid'
when not (parm = 2013 or parm = 2012) and cond = 3 then 'valid'
else 'invalid' end = 'valid';
dbms_output.put_line(result);
end proc2;
end p42;
/
所以proc1
基本上就是你的原始动态查询所做的事情,我相信。 proc2
正在使用您的case
构造。很明显,条件是完全弥补的,变量where
子句在这种形式下是愚蠢的,但这仅仅是case
。
使用parm(2013,2012,2011)的各种值运行会在两个过程中返回相同的行,因此它们在这个意义上是等效的
exec p42.proc1(2013);
One
exec p42.proc2(2013);
One
我怀疑你的最终情况是错误的。当然我猜,因为你发布的伪代码到目前为止从你的实际查询中删除,我们无法看到你可能做错了什么。但如果你做了这样的事情:
and case
when parm = 2013 and cond = 1 then 'valid'
when parm = 2012 and cond = 2 then 'valid'
when cond = 3 then 'valid'
else 'invalid' end = 'valid';
...然后cond = 3
将针对之前案例中尚未匹配的所有行进行评估,而不考虑parm
的值 - 例如如果parm = 2013
和cond = 3
,您的原始动态版本将无法获取。使用2013
,您将匹配One
和Three
。因此,您需要排除之前用作条件的所有parm
值,然后才能查看cond = 3
:
and case
when parm = 2013 and cond = 1 then 'valid'
when parm = 2012 and cond = 2 then 'valid'
when not (parm = 2013 or parm = 2012) and cond = 3 then 'valid'
else 'invalid' end = 'valid';
所以在您的伪代码中,这可能意味着:
select ... from table where condition1 and case
when (<condition1> and <one_new_condition_will_be_added_in_where_clause1>)
then 'valid'
when (<condition2> and <one_new_condition_will_be_added_in_where_clause2>
then 'valid'
when (<condition3> and <one_new_condition_will_be_added_in_where_clause3>)
then 'valid'
when (not (<condition1> or <condition2> or <condition3>)
and <one_new_condition_will_be_added_in_where_clause4>)
then 'valid'
else 'invalid'
end = 'valid'
我不一定说这是一个好主意,只是它应该有效。不知道为什么你的客户端反对动态SQL(所有这些?你的查询的某些特定方面?你对数据库产生了一些影响,例如通过不使用绑定变量?)以及你真正的查询正在做什么它是不可能知道的如果这种方法合适。可能有更好的方法,这可能会改善我们所知道的动态版本......
答案 1 :(得分:0)
我建议你在代码中使用PL / SQL函数。
select ...from table where 'Y' = IsRecordValid(...all relevant values in conditions...);
并在那里实施评估。我不确定你对性能的评价,但你可能对基于功能的索引感兴趣以提高你的表现。
其他方法是使用 dbms_sql 包,您可以使用它来动态创建SQL,但几乎可以保留静态查询的所有好处。