条件控制语句根据不同的条件去执行或者忽略一组程序代码,它可以通过 IF 或者 CASE 来实现。其中,IF 语句还包括以下几种形态:
IF THEN
IF THEN ELSE
IF THEN ELSIF
IF THEN 声明
IF THEN 声明的结构如下, 如果 condition 为 TRUE,则执行 statements:
IF condition THEN
statements
END IF;
示例如下:
obclient> DECLARE
-> V_EMP_NAME employees.first_name%TYPE := 'Adam';
-> V_EMP_SAL employees.salary%TYPE;
-> V_bonus number := 0;
-> BEGIN
-> SELECT salary INTO V_EMP_SAL FROM employees
-> WHERE first_name=V_EMP_NAME;
-> IF V_EMP_SAL > 10000 THEN
-> V_bonus := V_EMP_SAL * 0.4;
-> END IF;
-> DBMS_OUTPUT.PUT_LINE(V_EMP_NAME||'''bonus: '||V_bonus);
-> END;
-> /
Query OK, 0 rows affected (0.02 sec)
Adam'bonus: 0
在程序设计的时候,要避免下例中过于冗长的 IF 语句:
IF new_weight < minimum_weight THEN
isHealthy := TRUE;
ELSE
isHealthy := TRUE;
END IF;
优化写法为可以直接用布尔表达式赋值:isHealthy:= new_weight < minimum_weight;
布尔型变量可以保存TRUE,FALSE 或者 NULL,直接用于条件判断,所以要避免下例所示的写法:
IF isHealthy = FALSE THEN
RAISE start_one_month_diet;
END IF;
优化写法为:
IF NOT isHealth THEN
RAISE start_one_month_diet;
END IF;
IF THEN ELSE 声明
IF THEN ELSE 声明的结构如下, 如果 condition 为 TRUE,则执行 statements,否则执行 else_statements:
IF condition THEN
statements
ELSE
else_statements
END IF;
示例如下:
obclient> DECLARE
-> V_EMP_NAME employees.first_name%TYPE := 'Adam';
-> V_EMP_SAL employees.salary%TYPE;
-> V_bonus number := 0;
-> BEGIN
-> SELECT salary INTO V_EMP_SAL FROM employees
-> WHERE first_name=V_EMP_NAME;
-> IF V_EMP_SAL > 10000 THEN
-> V_bonus := V_EMP_SAL * 0.4;
-> ELSE
-> V_bonus := V_EMP_SAL * 0.25;
-> END IF;
-> DBMS_OUTPUT.PUT_LINE(V_EMP_NAME||'''bonus: '||V_bonus);
-> END;
-> /
Query OK, 0 rows affected (0.03 sec)
Adam'bonus: 2050
IF THEN ELSIF 声明
IF THEN ELSEF 声明的结构如下:
IF condition_1 THEN
statements_1
ELSIF condition_2 THEN
statements_2
[ ELSIF condition_3 THEN
statements_3
]...
[ ELSE
else_statements
]
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 声明如下:
IF condition_1 THEN statements_1;
ELSIF condition_2 THEN statements_2;
ELSIF condition_3 THEN statement_3;
END IF;
IF THEN ELSE 声明如下:
IF condition_1 THEN
statements_1;
ELSE
IF condition_2 THEN
statements_2;
ELSE
IF condition_3 THEN
statements_3;
END IF;
END IF;
END IF;
示例如下:
obclient> DECLARE
-> V_EMP_NAME employees.first_name%TYPE := 'Adam';
-> V_EMP_SAL employees.salary%TYPE;
-> V_bonus number := 0;
-> BEGIN
-> SELECT salary INTO V_EMP_SAL FROM employees
-> WHERE first_name=V_EMP_NAME;
-> IF V_EMP_SAL > 10000 THEN
-> V_bonus := V_EMP_SAL * 0.4;
-> ELSIF V_EMP_SAL > 5000 THEN
-> V_bonus := V_EMP_SAL * 0.25;
-> ELSE
-> V_bonus := V_EMP_SAL * 0.1;
-> END IF;
-> DBMS_OUTPUT.PUT_LINE(V_EMP_NAME||'''bonus: '||V_bonus);
-> END;
-> /
Query OK, 0 rows affected (0.03 sec)
Adam'bonus: 2050
简单 CASE 声明
最简单的 CASE 语句会计算一个单一表达式值并跟多个潜在值进行比较。
简单 CASE 声明的结构如下:
CASE selector
WHEN selector_value_1 THEN statements_1
WHEN selector_value_2 THEN statements_2 ...
WHEN selector_value_n THEN statements_n
[ ELSE
else_statements ]
END
CASE;
在上述示例中,selector 是一个表达式,每一个 selector_value 既可以是字面值,也可以是表达式。 简单 CASE 声明用 selector 的值逐个与 selector_value 比较,只要找到第一个相等的 selector_value,就不再比较其他selector_value。如果没有找到任何相等的 selector_value,CASE 就执行 else_statements。 如果这时 else_statements 不存在,程序会报错。
示例如下:
obclient> DECLARE
-> grade CHAR(1);
-> BEGIN
-> grade := 'B';
-> CASE grade
-> WHEN 'A' THEN DBMS_OUTPUT.PUT_LINE('PASS');
-> WHEN 'B' THEN DBMS_OUTPUT.PUT_LINE('SUSPEND');
-> WHEN 'C' THEN DBMS_OUTPUT.PUT_LINE('FAIL');
-> ELSE DBMS_OUTPUT.PUT_LINE('No such grade');
-> END CASE;
-> END;
-> /
Query OK, 0 rows affected (0.03 sec)
SUSPEND
程序发生报错的示例如下:
obclient> DECLARE
-> grade CHAR(1);
-> BEGIN
-> grade := 'D';
-> CASE grade
-> WHEN 'A' THEN DBMS_OUTPUT.PUT_LINE('PASS');
-> WHEN 'B' THEN DBMS_OUTPUT.PUT_LINE('SUSPEND');
-> WHEN 'C' THEN DBMS_OUTPUT.PUT_LINE('FAIL');
-> -- ELSE DBMS_OUTPUT.PUT_LINE('No such grade');
-> END CASE;
-> END;
-> /
ORA-00600: internal error code, arguments: -5571, Case not found for CASE statement
检索型 CASE 声明
检索型 CASE 语句中 CASE 后没有表达式要计算,而是 WHEN 后面分别有不同的布尔表达式。检索型 CASE 会计算多个布尔表达式并选择第一个结果为 TRUE 的分支。
检索型 CASE 声明的结构如下:
CASE
WHEN condition_1 THEN statements_1
WHEN condition_2 THEN statements_2 ...
WHEN condition_n THEN statements_n
[ ELSE
else_statements ]
END CASE;
检索型 CASE 声明会执行第一个 condition 为 TRUE 的 statements,之后不会再执行其他 statements。 如果所有condition 都不是 TRUE,则执行 else_statements。 如果这时 else_statements 不存在,程序会报错。
与简单 CASE 声明相对应的检索型 CASE 声明示例如下:
obclient> DECLARE
-> grade CHAR(1);
-> BEGIN
-> grade := 'D';
-> CASE
-> WHEN grade = 'A' THEN DBMS_OUTPUT.PUT_LINE('PASS');
-> WHEN grade = 'B' THEN DBMS_OUTPUT.PUT_LINE('SUSPEND');
-> WHEN grade = 'C' THEN DBMS_OUTPUT.PUT_LINE('FAIL');
-> ELSE DBMS_OUTPUT.PUT_LINE('UNEXPECTED');
-> END CASE;
-> END;
-> /
Query OK, 0 rows affected (0.04 sec)
UNEXPECTED