CASE语句与CASE表达式

来源:互联网 发布:ubuntu root密码设置 编辑:程序博客网 时间:2024/05/16 12:09
CASE语句与CASE表达式

转自:http://blog.csdn.net/leshami/article/details/7340187

case语句与case表达式是plsql流程控制的重要组成部分,尽管其使用方法较为简单,但容易混淆。
本文将描述case语句与case表达式并给出演示以便于更好理解两者的异同及使用时的注意事项。

一、简单case语句

-->语法

CASE SELECTOR
WHEN EXPRESSION 1 THEN STATEMENT 1;
WHEN EXPRESSION 2 THEN STATEMENT 2;
...
WHEN EXPRESSION N THEN STATEMENT N;
ELSE STATEMENT N 1;
END CASE;

--简单的case语句是指SELECTOR中得到的值或结果与EXPRESSIONn中的值或结果相匹配,一旦找到匹配,则对应的语句被执行。直到找到为止。
--如果对应的EXPRESSION n 中没有匹配,则此时ELSE上阵,执行其后对应的语句。
--ELSE为可选项。如省略且when条件中未找到任何匹配项,则收到case_not_found异常。
-->演示简单case语句

sys@ORCL> DECLARE
   v_num    NUMBER:= &in_num;
   v_flag   NUMBER;
BEGIN
   v_flag := MOD (v_num, 2);
6
   CASE v_flag
      WHEN 0
      THEN
10          DBMS_OUTPUT.put_line (v_num || ' is even number');
11       WHEN 1
12       THEN
13          DBMS_OUTPUT.put_line (v_num || ' is odd number');
14       ELSE
15          NULL;
16    END CASE;
17  END;
18  /

Enter value for in_num: 5
5 is odd number
PL/SQL procedure successfully completed.


二、搜索式case语句

-->语法

CASE
WHEN SEARCH CONDITION 1 THEN STATEMENT 1;
WHEN SEARCH CONDITION 2 THEN STATEMENT 2;
...
WHEN SEARCH CONDITION N THEN STATEMENT N;
ELSE STATEMENT N 1;
END CASE;

--搜索式case语句与简单case语句长相不一样。首先是case 之后没有接selector,其次是when之后的SEARCHCONDITION n得到的结果为布尔型,
--当搜索到第一个为TRUE的STATEMENT的结果会被返回。若果所有的when之后的SEARCHCONDITION没有为TRUE的,则else之后的STATEMENT
--的结果会被返回。如果此时省略了else子句,等同于简单case语句,同样会收到case_not_found异常。谁叫他俩一母同胞呢?
-->下面演示搜索式case

scott@ORCL> DECLARE
   v_num   NUMBER :=&in_num;
BEGIN
   CASE
      WHEN v_num > 0
      THEN
         DBMS_OUTPUT.put_line (v_num || ' is a positive number ');
      WHEN v_num < 0
      THEN
10          DBMS_OUTPUT.put_line (v_num || ' is a negative number ');
11       ELSE
12          DBMS_OUTPUT.put_line (v_num || ' is zero ');
13    END CASE;
14  END;
15  /

Enter value for in_num: -3
-3 is a negative number

-->如下例所示所有的when之后的没有一个为true,且省略了else子句,那么迎接你的是CASEnot found

scott@ORCL> DECLARE
   v_num   NUMBER :=&in_num;
BEGIN
   CASE
      WHEN v_num > 0
      THEN
         DBMS_OUTPUT.put_line (v_num || ' is a positive number ');
      WHEN v_num < 0
      THEN
10          DBMS_OUTPUT.put_line (v_num || ' is a negative number ');
11    END CASE;
12  END;
13  /

Enter value for in_num: 0

DECLARE
*
ERROR at line 1:
ORA-06592: CASE not found while executing CASE statement
ORA-06512: at line 4


三、简单case语句与搜索式case语句的异同

--相同点:两者都用于根据不同的条件,来执行与之对应的语句或完成特定的任务,甚至某些情况下可以互换替换。

--不同点:

--简单case语句提供一个selector选择器,且EXPRESSION的数据类型一定与selector的数据类型匹配,否则报错。
--搜索case语句没有selector选择器,且when子句之后得到的结果一定是一个布尔型值(NULL,TRUR,FALSE)

--下面的例子是一个简单case与搜索case之间互换的例子,同时该方式也实现了行到列的转行。

scott@ORCL> select sum(case when deptno=20 then salend) as sal_sum_20,  -->搜索式case方式
sum(case when deptno=30 then sal end) assal_sum_30
from emp where comm>300;

SAL_SUM_20 SAL_SUM_30
---------- ----------
13075      8300

scott@ORCL> select sum(case deptno when 20 then salend) as sal_sum_20, -->简单case方式
sum(case deptno when 30 then sal end) assal_sum_30
from emp where comm>300;

SAL_SUM_20 SAL_SUM_30
---------- ----------
13075      8300


--使用搜索式case方式,当selector选择器的数据类型不是为布尔型时,收到类型不匹配的提示,如下示例:

scott@ORCL> DECLARE
   v_num    NUMBER:= &sv_num;
   v_flag   NUMBER;
BEGIN
   CASE v_flag
      WHEN MOD(v_num, 2) = 0
      THEN
         DBMS_OUTPUT.PUT_LINE (v_num || ' is even number');
      ELSE
10          DBMS_OUTPUT.PUT_LINE (v_num || ' is odd number');
11    END CASE;
12  END;
13  /

Enter value for sv_num: 7

CASE v_flag
*
ERROR at line 5:
ORA-06550: line 5, column 9:
PLS-00615: type mismatch found at 'V_FLAG' between CASE operand andWHEN operands
ORA-06550: line 5, column 4:
PL/SQL: Statement ignored


四、case表达式


--Case表达式与Case语句,如何理解呢?我们不妨来望文生义,便于记忆。分析如下:
--Case表达式,那么when 之后接的一定是表达式或一个特定值。
--Case语句,那么when之后接的一定一个语句,或函数,或计算表达式。既然是语句则一定带有分号。
--最后一点区别是case以end结束,而case语句则是以case end结束。

scott@ORCL> DECLARE
   v_num     NUMBER := &in_num;
   v_flag    NUMBER;
   v_result   VARCHAR2 (20);
   BEGIN
   v_flag := MOD (v_num, 2);
7
   v_result :=
      CASE v_flag
10          WHEN 0 THEN TO_CHAR (v_num) || ' is even number'
11          WHEN 1 THEN TO_CHAR (v_num) || ' is odd number'
12       END;
13    DBMS_OUTPUT.put_line (v_result);
14  END;
15  /

Enter value for in_num: 3
3 is odd number

PL/SQL procedure successfully completed.

-->下面的写法也较为常用

scott@ORCL> SELECT ename,
       CASE deptno
          WHEN 20 THEN 'Developement'
          WHEN 30 THEN 'Sales'
          ELSE 'Clerk'
       END
          AS deptname
FROM scott.emp;
8

ENAME     DEPTNAME
---------- ------------
john      Clerk
Henry     Developement
ALLEN     Sales
WARD      Sales
..........


五、case嵌套


--case的嵌套就是case语句和表达式中嵌套case语句与表达式,理解了case的用法,case嵌套并不难。注意case与caseend/end的匹配问题
--下面是一个使用case表达式演示的case嵌套示例。
--更新表emp中的comm列,首先case是根据部门来判断,其下又嵌套了一个case,根据comm值的不同来确定新的comm值。

UPDATE scott.emp
SET comm =
CASE deptno

WHEN 20 THEN CASE
WHEN comm IS NULL THEN 500
WHEN comm < 200 THEN 300
ELSE 100
END

WHEN 30 THEN CASE
WHEN comm IS NULL THEN 700
WHEN comm < 200 THEN 500
ELSE 200
END

ELSE 1000
END;

0 0