在oracle中的where子句的case语句中传递多个值

时间:2017-06-16 12:56:04

标签: sql oracle oracle11g

我需要从用户那里获得输入,该输入将被传递给查询并与现有值AA进行比较。如果是AA,那么将选择ABC模式。

以下查询正常,

select distinct a.TABLE_OWNER,a.table_name,a.index_name,b.column_name
from dba_indexes a, dba_ind_columns b
where a.index_name=b.index_name 
and a.table_name = b.table_name
and a.table_owner in ( case when &user_input = 'AA' then 'ABC' end )
order by 1,2,3,4; 

但如果我不得不再提一个架构名称,比如DEF,我该怎么办呢。我尝试使用逗号,但它抛出错误,"缺少右括号"

select distinct a.TABLE_OWNER,a.table_name,a.index_name,b.column_name
from dba_indexes a, dba_ind_columns b
where a.index_name=b.index_name 
and a.table_name = b.table_name
and a.table_owner in ( case when &user_input = 'AA' then 'ABC','DEF' end )
order by 1,2,3,4; 

错误

ORA-00907: missing right parenthesis
00907. 00000 -  "missing right parenthesis"
*Cause:    
*Action:
Error at Line: 5 Column: 63

我从Ask Tom网站上读到,只返回一个标量值,是否可以返回一堆值?

3 个答案:

答案 0 :(得分:1)

不要使用case。我想你打算:

and ( &user_input <> 'AA' or a.table_owner in ('ABC','DEF') )

这是猜测。当前代码更像是:

and ( &user_input = 'AA' and a.table_owner in ('ABC','DEF') )

因为case没有else子句。

答案 1 :(得分:1)

据我所知,CASE表达式必须生成单个标量值。但您可以按如下方式重写WHERE子句:

where
    a.index_name = b.index_name and
    a.table_name = b.table_name and
    (&user_input = 'AA' and
    a.table_owner in ('ABC', 'DEF') )

答案 2 :(得分:1)

这是在WHERE子句中使用CASE的正确方法。

...
and case &user_input when 'AA' then case when a.table_owner in ('ABC', DEF') then 1 end
                     else           case when <your other conditions here>   then 1 end
    end
    = 1

工作原理:

首先将&user_input与AA&#39;进行比较。如果为true,则将a.table_owner与&#39; ABC&#39;进行比较。和&#39; DEF&#39;,如果它们中的一个CASE表达式的值为1,否则为NULL(默认情况下)。如果&user_input不是&#39; AA&#39; (它也可能是NULL),然后评估你没有说明的其他条件,如果为true,则CASE表达式的计算结果为1,否则为NULL。

然后将CASE表达式的结果与数字1进行比较。

一个好处是:如果&#34;其他条件&#34;由于短路评估,如果&user_input是&#39; AA&#39;这种安排是昂贵的(很多计算,诸如此类),这种安排保证它们不会被执行。如果您仅使用ANDOR运算符编写条件,则无此控制

另请注意外部CASE中的CASE表达式的NESTING - 这在许多情况下都非常有效且有用。