CASE 表达式返回一个值,该值在 CASE 表达式位于某一表达式内时被替换。

CASE 表达式有两种格式:一种称为搜索 CASE,另一种使用选择器。

选择器 CASE 表达式

选择器 CASE 表达式尝试将一个称为选择器的表达式与一个或多个 WHEN 子句中指定的表达式进行匹配。result 是使用 CASE 表达式的上下文中类型兼容的一个表达式。如果找到匹配项,则 CASE 表达式将返回对应 THEN 子句中给出的值。如果没有匹配项,则返回 ELSE 后面的值。如果省略 ELSE,则 CASE 表达式返回空值。

CASE selector-expression
  WHEN match-expression THEN
    result
[ WHEN match-expression THEN
    result
[ WHEN match-expression THEN
    result ] ...]
[ ELSE
    result ]
END;

match-expression 将按它在 CASE 表达式中出现的顺序进行求值。result 是使用 CASE 表达式的上下文中类型兼容的一个表达式。当遇到等于 selector-expression 的第一个 match-expression 时,对应 THEN 子句中的 result 将作为 CASE 表达式的值返回。如果没有等于 selector-expression 的 match-expression,则返回 ELSE 后面的 result。如果未指定 ELSE,则 CASE 表达式返回空值。

以下示例使用选择器 CASE 表达式根据部门编号,将部门名称分配给一个变量。

DECLARE
    v_empno         emp.empno%TYPE;
    v_ename         emp.ename%TYPE;
    v_deptno        emp.deptno%TYPE;
    v_dname         dept.dname%TYPE;
    CURSOR emp_cursor IS SELECT empno, ename, deptno FROM emp;
BEGIN
    OPEN emp_cursor;
    DBMS_OUTPUT.PUT_LINE('EMPNO    ENAME     DEPTNO    DNAME');
    DBMS_OUTPUT.PUT_LINE('-----    -------   ------    ----------');
    LOOP
        FETCH emp_cursor INTO v_empno, v_ename, v_deptno;
        EXIT WHEN emp_cursor%NOTFOUND;
        v_dname :=
            CASE v_deptno
                WHEN 10 THEN 'Accounting'
                WHEN 20 THEN 'Research'
                WHEN 30 THEN 'Sales'
                WHEN 40 THEN 'Operations'
                ELSE 'unknown'
            END;
        DBMS_OUTPUT.PUT_LINE(v_empno || '     ' || RPAD(v_ename, 10) ||
            '  ' || v_deptno || '      ' || v_dname);
    END LOOP;
    CLOSE emp_cursor;
END;

下面是此程序的输出。

EMPNO    ENAME     DEPTNO    DNAME
-----    -------   ------    ----------
7369     SMITH       20      Research
7499     ALLEN       30      Sales
7521     WARD        30      Sales
7566     JONES       20      Research
7654     MARTIN      30      Sales
7698     BLAKE       30      Sales
7782     CLARK       10      Accounting
7788     SCOTT       20      Research
7839     KING        10      Accounting
7844     TURNER      30      Sales
7876     ADAMS       20      Research
7900     JAMES       30      Sales
7902     FORD        20      Research
7934     MILLER      10      Accounting

搜索 CASE 表达式

搜索 CASE 表达式使用一个或多个布尔表达式来确定要返回的结果值。

CASE WHEN boolean-expression THEN
    result
[ WHEN boolean-expression THEN
    result
 [ WHEN boolean-expression THEN
    result ] ...]
[ ELSE
    result ]
END;

boolean-expression 按它在 CASE 表达式中出现的顺序进行求值。result 是使用 CASE 表达式的上下文中类型兼容的一个表达式。当遇到求值结果为 true 的第一个 boolean-expression 时,对应 THEN 子句中的 result 将作为 CASE 表达式的值返回。如果没有求值结果为 true 的 boolean-expression,则将返回 ELSE 后面的 result。如果未指定 ELSE,则 CASE 表达式返回空值。

以下示例使用搜索 CASE 表达式根据部门编号,将部门名称分配给一个变量。

DECLARE
    v_empno         emp.empno%TYPE;
    v_ename         emp.ename%TYPE;
    v_deptno        emp.deptno%TYPE;
    v_dname         dept.dname%TYPE;
    CURSOR emp_cursor IS SELECT empno, ename, deptno FROM emp;
BEGIN
    OPEN emp_cursor;
    DBMS_OUTPUT.PUT_LINE('EMPNO    ENAME     DEPTNO    DNAME');
    DBMS_OUTPUT.PUT_LINE('-----    -------   ------    ----------');
    LOOP
        FETCH emp_cursor INTO v_empno, v_ename, v_deptno;
        EXIT WHEN emp_cursor%NOTFOUND;
        v_dname :=
            CASE
                WHEN v_deptno = 10 THEN 'Accounting'
                WHEN v_deptno = 20 THEN 'Research'
                WHEN v_deptno = 30 THEN 'Sales'
                WHEN v_deptno = 40 THEN 'Operations'
                ELSE 'unknown'
            END;
        DBMS_OUTPUT.PUT_LINE(v_empno || '     ' || RPAD(v_ename, 10) ||
            '  ' || v_deptno || '      ' || v_dname);
    END LOOP;
    CLOSE emp_cursor;
END;

下面是此程序的输出。

EMPNO    ENAME     DEPTNO    DNAME
-----    -------   ------    ----------
7369     SMITH       20      Research
7499     ALLEN       30      Sales
7521     WARD        30      Sales
7566     JONES       20      Research
7654     MARTIN      30      Sales
7698     BLAKE       30      Sales
7782     CLARK       10      Accounting
7788     SCOTT       20      Research
7839     KING        10      Accounting
7844     TURNER      30      Sales
7876     ADAMS       20      Research
7900     JAMES       30      Sales
7902     FORD        20      Research
7934     MILLER      10      Accounting