比较变量时如何在where语句中使用CASE和IN

时间:2019-04-02 09:28:02

标签: oracle plsql case

我不想使用动态SQL,所以我正在尝试其他方式来更改where语句。

在我的WHERE语句中,有一行:

AND c.nregion = pnregion

pnregion是俄罗斯的一些地区。该语句可帮助我的光标更快地工作,因为Oracle不必浏览整个表。

问题在于,如果pnregion等于47或78,则此行应如下所示

AND c.nregion in (47, 78)

该怎么做?我应该以某种方式使用CASE还是在光标之外可以做一些事情?

3 个答案:

答案 0 :(得分:2)

您可以使用:

WHERE ( c.nregion = pnregion
      OR (   pnregion  IN ( 47, 78 )
         AND c.nregion IN ( 47, 78 )
         )
      )

如果您想要两个以上的值,则可以轻松扩展此值,因为可以将这些值添加到两个IN过滤器中。

答案 1 :(得分:1)

您可以使用decode函数根据代码47/78添加另一个选项:

AND (c.nregion  = pnregion OR c.nregion = decode(pnregion, 47, 78, 78, 47)) 

答案 2 :(得分:1)

如果我理解这个问题,则是 IN列表中的各种元素困扰着您。换句话说,除非您使用

,否则不能将逗号分隔的值放入IN列表中
  • 切换到动态SQL(这是您不想要的)
  • 将这些值分成几行

这是一个基于斯科特模式的示例;希望您能理解。

这是您当前拥有的:

SQL> create or replace procedure p_test (pnregion in varchar2)
  2  is
  3    cursor c1 is select empno, ename from emp
  4      where deptno in pnregion;
  5  begin
  6    for cr in c1 loop
  7      dbms_output.put_line(cr.ename);
  8    end loop;
  9  end;
 10  /

Procedure created.

SQL> -- This is OK
SQL> exec p_test('10');
CLARK
KING
MILLER

PL/SQL procedure successfully completed.

SQL> -- This is not OK
SQL> exec p_test('10, 20');
BEGIN p_test('10, 20'); END;

*
ERROR at line 1:
ORA-01722: invalid number
ORA-06512: at "SCOTT.P_TEST", line 6
ORA-06512: at line 1


SQL>

现在,将逗号分隔的值拆分为行,并观察其工作:

SQL> create or replace procedure p_test (pnregion in varchar2)
  2  is
  3    cursor c1 is select empno, ename from emp
  4      where deptno in (select regexp_substr(pnregion, '[^,]+', 1, level)
  5                       from dual
  6                       connect by level <= regexp_count(pnregion, ',') + 1
  7                      );
  8  begin
  9    for cr in c1 loop
 10      dbms_output.put_line(cr.ename);
 11    end loop;
 12  end;
 13  /

Procedure created.

SQL> -- This is OK
SQL> exec p_test('10');
CLARK
KING
MILLER

PL/SQL procedure successfully completed.

SQL> -- This is also OK now
SQL> exec p_test('10, 20');
SMITH
JONES
CLARK
SCOTT
KING
ADAMS
FORD
MILLER

PL/SQL procedure successfully completed.

SQL> -- Or even some more values:
SQL> exec p_test('10, 20,30');
SMITH
ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER
ADAMS
JAMES
FORD
MILLER

PL/SQL procedure successfully completed.

SQL>