条件控制语句根据不同的条件去执行或者忽略一组程序代码,它可以通过 IF 或者 CASE 来实现。其中,IF 语句还包括以下几种形态:

  • IF THEN

  • IF THEN ELSE

  • IF THEN ELSIF

IF THEN 声明

IF THEN 声明的结构如下, 如果 condition 为 TRUE,则执行 statements:

  1. IF condition THEN
  2. statements
  3. END IF;

示例如下:

  1. obclient> DECLARE
  2. -> V_EMP_NAME employees.first_name%TYPE := 'Adam';
  3. -> V_EMP_SAL employees.salary%TYPE;
  4. -> V_bonus number := 0;
  5. -> BEGIN
  6. -> SELECT salary INTO V_EMP_SAL FROM employees
  7. -> WHERE first_name=V_EMP_NAME;
  8. -> IF V_EMP_SAL > 10000 THEN
  9. -> V_bonus := V_EMP_SAL * 0.4;
  10. -> END IF;
  11. -> DBMS_OUTPUT.PUT_LINE(V_EMP_NAME||'''bonus: '||V_bonus);
  12. -> END;
  13. -> /
  14. Query OK, 0 rows affected (0.02 sec)
  15. Adam'bonus: 0

在程序设计的时候,要避免下例中过于冗长的 IF 语句:

  1. IF new_weight < minimum_weight THEN
  2. isHealthy := TRUE;
  3. ELSE
  4. isHealthy := TRUE;
  5. END IF;

优化写法为可以直接用布尔表达式赋值:isHealthy:= new_weight < minimum_weight;

布尔型变量可以保存TRUE,FALSE 或者 NULL,直接用于条件判断,所以要避免下例所示的写法:

  1. IF isHealthy = FALSE THEN
  2. RAISE start_one_month_diet;
  3. END IF;

优化写法为:

  1. IF NOT isHealth THEN
  2. RAISE start_one_month_diet;
  3. END IF;

IF THEN ELSE 声明

IF THEN ELSE 声明的结构如下, 如果 condition 为 TRUE,则执行 statements,否则执行 else_statements:

  1. IF condition THEN
  2. statements
  3. ELSE
  4. else_statements
  5. END IF;

示例如下:

  1. obclient> DECLARE
  2. -> V_EMP_NAME employees.first_name%TYPE := 'Adam';
  3. -> V_EMP_SAL employees.salary%TYPE;
  4. -> V_bonus number := 0;
  5. -> BEGIN
  6. -> SELECT salary INTO V_EMP_SAL FROM employees
  7. -> WHERE first_name=V_EMP_NAME;
  8. -> IF V_EMP_SAL > 10000 THEN
  9. -> V_bonus := V_EMP_SAL * 0.4;
  10. -> ELSE
  11. -> V_bonus := V_EMP_SAL * 0.25;
  12. -> END IF;
  13. -> DBMS_OUTPUT.PUT_LINE(V_EMP_NAME||'''bonus: '||V_bonus);
  14. -> END;
  15. -> /
  16. Query OK, 0 rows affected (0.03 sec)
  17. Adam'bonus: 2050

IF THEN ELSIF 声明

IF THEN ELSEF 声明的结构如下:

  1. IF condition_1 THEN
  2. statements_1
  3. ELSIF condition_2 THEN
  4. statements_2
  5. [ ELSIF condition_3 THEN
  6. statements_3
  7. ]...
  8. [ ELSE
  9. else_statements
  10. ]
  11. END IF;

当 condition_1 的值为 TRUE 时,执行 statements_1 语句,并结束程序;否则,当 condition_2 的值为 TRUE 时,执行 statements_2 语句,并结束程序;以此类推,直到 statements_n 均不为 TRUE 时,执行 else_statements 语句,并结束程序。

因为 IF THEN 声明是可以嵌套的,所以IF THEN ELSIF 和 IF THEN ELSE 两个声明是等价的。

IF THEN ELSIF 声明如下:

  1. IF condition_1 THEN statements_1;
  2. ELSIF condition_2 THEN statements_2;
  3. ELSIF condition_3 THEN statement_3;
  4. END IF;

IF THEN ELSE 声明如下:

  1. IF condition_1 THEN
  2. statements_1;
  3. ELSE
  4. IF condition_2 THEN
  5. statements_2;
  6. ELSE
  7. IF condition_3 THEN
  8. statements_3;
  9. END IF;
  10. END IF;
  11. END IF;

示例如下:

  1. obclient> DECLARE
  2. -> V_EMP_NAME employees.first_name%TYPE := 'Adam';
  3. -> V_EMP_SAL employees.salary%TYPE;
  4. -> V_bonus number := 0;
  5. -> BEGIN
  6. -> SELECT salary INTO V_EMP_SAL FROM employees
  7. -> WHERE first_name=V_EMP_NAME;
  8. -> IF V_EMP_SAL > 10000 THEN
  9. -> V_bonus := V_EMP_SAL * 0.4;
  10. -> ELSIF V_EMP_SAL > 5000 THEN
  11. -> V_bonus := V_EMP_SAL * 0.25;
  12. -> ELSE
  13. -> V_bonus := V_EMP_SAL * 0.1;
  14. -> END IF;
  15. -> DBMS_OUTPUT.PUT_LINE(V_EMP_NAME||'''bonus: '||V_bonus);
  16. -> END;
  17. -> /
  18. Query OK, 0 rows affected (0.03 sec)
  19. Adam'bonus: 2050

简单 CASE 声明

最简单的 CASE 语句会计算一个单一表达式值并跟多个潜在值进行比较。

简单 CASE 声明的结构如下:

  1. CASE selector
  2. WHEN selector_value_1 THEN statements_1
  3. WHEN selector_value_2 THEN statements_2 ...
  4. WHEN selector_value_n THEN statements_n
  5. [ ELSE
  6. else_statements ]
  7. END
  8. CASE;

在上述示例中,selector 是一个表达式,每一个 selector_value 既可以是字面值,也可以是表达式。 简单 CASE 声明用 selector 的值逐个与 selector_value 比较,只要找到第一个相等的 selector_value,就不再比较其他selector_value。如果没有找到任何相等的 selector_value,CASE 就执行 else_statements。 如果这时 else_statements 不存在,程序会报错。

示例如下:

  1. obclient> DECLARE
  2. -> grade CHAR(1);
  3. -> BEGIN
  4. -> grade := 'B';
  5. -> CASE grade
  6. -> WHEN 'A' THEN DBMS_OUTPUT.PUT_LINE('PASS');
  7. -> WHEN 'B' THEN DBMS_OUTPUT.PUT_LINE('SUSPEND');
  8. -> WHEN 'C' THEN DBMS_OUTPUT.PUT_LINE('FAIL');
  9. -> ELSE DBMS_OUTPUT.PUT_LINE('No such grade');
  10. -> END CASE;
  11. -> END;
  12. -> /
  13. Query OK, 0 rows affected (0.03 sec)
  14. SUSPEND

程序发生报错的示例如下:

  1. obclient> DECLARE
  2. -> grade CHAR(1);
  3. -> BEGIN
  4. -> grade := 'D';
  5. -> CASE grade
  6. -> WHEN 'A' THEN DBMS_OUTPUT.PUT_LINE('PASS');
  7. -> WHEN 'B' THEN DBMS_OUTPUT.PUT_LINE('SUSPEND');
  8. -> WHEN 'C' THEN DBMS_OUTPUT.PUT_LINE('FAIL');
  9. -> -- ELSE DBMS_OUTPUT.PUT_LINE('No such grade');
  10. -> END CASE;
  11. -> END;
  12. -> /
  13. ORA-00600: internal error code, arguments: -5571, Case not found for CASE statement

检索型 CASE 声明

检索型 CASE 语句中 CASE 后没有表达式要计算,而是 WHEN 后面分别有不同的布尔表达式。检索型 CASE 会计算多个布尔表达式并选择第一个结果为 TRUE 的分支。

检索型 CASE 声明的结构如下:

  1. CASE
  2. WHEN condition_1 THEN statements_1
  3. WHEN condition_2 THEN statements_2 ...
  4. WHEN condition_n THEN statements_n
  5. [ ELSE
  6. else_statements ]
  7. END CASE;

检索型 CASE 声明会执行第一个 condition 为 TRUE 的 statements,之后不会再执行其他 statements。 如果所有condition 都不是 TRUE,则执行 else_statements。 如果这时 else_statements 不存在,程序会报错。

与简单 CASE 声明相对应的检索型 CASE 声明示例如下:

  1. obclient> DECLARE
  2. -> grade CHAR(1);
  3. -> BEGIN
  4. -> grade := 'D';
  5. -> CASE
  6. -> WHEN grade = 'A' THEN DBMS_OUTPUT.PUT_LINE('PASS');
  7. -> WHEN grade = 'B' THEN DBMS_OUTPUT.PUT_LINE('SUSPEND');
  8. -> WHEN grade = 'C' THEN DBMS_OUTPUT.PUT_LINE('FAIL');
  9. -> ELSE DBMS_OUTPUT.PUT_LINE('UNEXPECTED');
  10. -> END CASE;
  11. -> END;
  12. -> /
  13. Query OK, 0 rows affected (0.04 sec)
  14. UNEXPECTED