和大多数程序语言一样,PL/SQL也有控制语句执行的结构,主要包括:
1、顺序结构:程序从上往下执行逐条语句,就是顺序结构;
2、分支条件判断:分支条件判断主要是指的IF语句和CASE语句。
3、循环语句:循环结构主要指的是REPEAT、LOOP和DO WHILE语句。
本章节主要讲解条件判断语句的用法。
一、 IF 语句的用法
IF 语句的基本格式为:
IF conditionTHEN
statements;
[ ELSIF conditionTHEN
-- 注意,这里的ELSIF中间没有E,ELSIF可以出现任意次
statements;]
[ ELSE
statements;
]
END IF;
IF 后面的判断条件可以是布尔值,常量或表达式,判断结果为TRUE, FALSE或NULL,其中NULL这种情况是PL/SQL中特有的,其他编程语言并不常见;
如果IF后的条件判断结果为TRUE,就执行THEN后面的语句;如果结果为FALSE和NULL,则不执行THEN后面的结果,而执行ELSE后面的语句。
下面看一个简单的例子:
SQL> edit
DECLARE
v_myage number :=31;
BEGIN
IF v_myage < 11
THEN
DBMS_OUTPUT.PUT_LINE(' I am a child');
ELSE
DBMS_OUTPUT.PUT_LINE( ' I am not achild! ');
-- 由于IF后的条件判断结果为FALSE,所以会执行这条语句
END IF;
END;
/
SQL> /
I am not a child!
PL/SQL procedure successfullycompleted.
现在为上述例子多添加几条分支进行条件判断:
SQL> edit
BEGIN
IF v_myage < 11 THEN
DBMS_OUTPUT.PUT_LINE(' I am achild ');
ELSIF v_myage < 20 THEN
DBMS_OUTPUT.PUT_LINE( 'Iam young ');
ELSIF v_myage < 30 THEN
DBMS_OUTPUT.PUT_LINE( 'Iam in my twenties');
ELSIF v_myage < 40 THEN
DBMS_OUTPUT.PUT_LINE( 'I am in mythirties');
-- 由于31大于11,20,30,而小于40,所以执行这条语句
ELSE
DBMS_OUTPUT.PUT_LINE( 'Iam always young ');
END IF;
END;
/
SQL> /
I am in my thirties
PL/SQL procedure successfullycompleted.
如果IF条件判断的结果为NULL,则不会执行THEN后面的语句。
SQL> edit
DECLARE
v_myage NUMBER;
BEGIN
-- IF v_myage IS NULL
--这里的结果时TRUE,因为判断是变量v_myage是否为NULL值,是就为TRUE,不是就为FALSE
IF v_myage < 11 THEN
-- 如果判断的条件为NULL值,则结果为NULL
THEN
DBMS_OUTPUT.PUT_LINE(' I am a child');
ELSE
DBMS_OUTPUT.PUT_LINE( ' I am not achild! ');
END IF;
END;
/
SQL> /
I am not a child
PL/SQL procedure successfullycompleted.
IF 语句的条件还可以使用AND,OR,NOT等逻辑符进行组合。
IF条件判断语句中需要注意一些细节:
a. IF 和 END IF必须配对出现;
b. END IF中间有空格;
c. ELSIF中间没有E;
d. 在END IF后面有分号“;”
二、 CASE的用法
CASE实际上IF语句的变体,当IF语句有大量类似的ELSIF判断条件时,就可以使用CASE来进行简化。CASE的用法可以分为两种,一种是CASE表达式,另一种是CASE语句。
(1)CASE表达式:
CASE 表达式的基本格式为:
CASE selector
WHENexpression1 THEN result1
WHENexpression2 THEN result2
...
WHENexpressionN THEN resultN
[ELSEresultN+1]
END;
其中selector选择值如果等于expression1的值,就执行result1,如果等于expression2,就执行result2...以此类推,如果没有expression的值能与之匹配的,就执行resultN+1。
CASE表达式可以分为simple CASE和Searched CASE,其中simple CASE是指CASE后面会跟一个选择值,然后将条件表达式的结果和这个选择值进行比较,如下述这个例子:
SQL> edit
SET VERIFY OFF
DECLARE
v_grade CHAR(1) := UPPER('&grade');
v_appraisal VARCHAR2(20);
BEGIN
v_appraisal := CASE v_grade
WHEN 'A' THEN 'Excellent'
WHEN 'B' THEN 'Very Good'
WHEN 'c' THEN 'Good'
ELSE 'No such grade'
END;
-- 从CASE到END这一部分是simple CASE,其运行结果作为一个值赋给v_appraisal这个变量。
DBMS_OUTPUT.PUT_LINE ('Grade: ' ||v_grade || ' Appraisal ' || v_appraisal);
END;
SQL> /
Enter value for grade: a
Grade: A Appraisal Excellent
PL/SQL procedure successfullycompleted.
SQL> /
Enter value for grade: s
Grade: S Appraisal No suchgrade
PL/SQL procedure successfullycompleted.
Searched CASE 中CASE后面没有选择值selector,而是直接判断关键字WHEN后面表达式的布尔值,如下面这个例子:
SQL> edit
DECLARE
v_grade CHAR(1) := UPPER('&grade');
v_appraisal VARCHAR2(20);
BEGIN
v_appraisal := CASE
-- 这里的CASE没有选择值了
WHEN v_grade = 'A' THEN'Excellent'
-- 直接在条件判断部分完成布尔值的返回
WHEN v_grade IN ('B','C') THEN'Good'
ELSE 'No such grade'
END;
DBMS_OUTPUT.PUT_LINE ('Grade: ' ||v_grade || ' Appraisal ' ||v_appraisal);
END;
/
SQL>/
Enter value for grade: A
Grade: A Appraisal Excellent
PL/SQL procedure successfullycompleted.
SQL> /
Enter value for grade: o
Grade: O Appraisal No such grade
PL/SQL procedure successfullycompleted.
SQL> /
Enter value for grade: b
Grade: B Appraisal Good
PL/SQL procedure successfullycompleted.
(2)CASE语句
CASE语句就是一条条独立的语句,它不能将运行结果再赋值给其他的变量了。
如下面这个例子:
SQL> edit
DECLARE
v_deptid NUMBER;
v_deptname VARCHAR2(20);
V_emps NUMBER;
v_mngid NUMBER:= 108;
BEGIN
CASE v_mngid
WHEN 108 THEN
SELECT department_id,department_name
INTO v_deptid, v_deptname
FROM departments
WHERE manager_id = 108;
SELECT count(*)
INTO v_emps
FROM employees
WHERE department_id = v_deptid;
--CASE语句不再作为一个整体将运行结果赋值给其他变量了
WHEN 200 THEN
SELECT department_id,department_name
INTO v_deptid, v_deptname
FROM departments
WHERE manager_id = 200;
SELECT count(*)
INTO v_emps
FROM employees
WHERE department_id = v_deptid;
ELSE
SELECT department_id,department_name
INTO v_deptid, v_deptname
FROM departments
WHERE manager_id = 100;
SELECT count(*)
INTO v_emps
FROM employees
WHERE department_id = v_deptid;
END CASE;
--CASE语句中必须有END CASE,如果是CASE表达式就不需要END CASE。
DBMS_OUTPUT.PUT_LINE('You are workingin the ' || v_deptname || ' department. There are ' ||v_emps || 'employees inthis department');
END;
/
SQL> /
You are working in theFinance department. There are 6 employees in this
department
PL/SQL procedure successfullycompleted.
CASE语句也分为SimpleCASE语句和Searched CASE语句。他们之间的区别和CASE表达式一样。上述例子属于SimpleCASE的用法,如果要使用Searched CASE语句,可以写成如下形式:
SQL> edit
DECLARE
v_deptid NUMBER;
v_deptname VARCHAR2(20);
V_emps NUMBER;
v_mngid NUMBER:= 100;
BEGIN
CASE
WHEN v_mngid = 108 THEN
--v_mngid不作为选择值,而是直接在WHEN后面进行判断
SELECT department_id,department_name
INTO v_deptid, v_deptname
FROM departments
WHERE manager_id = 108;
SELECT count(*)
INTO v_emps
FROM employees
WHERE department_id = v_deptid;
WHEN v_mngid = 200 THEN
SELECT department_id,department_name
INTO v_deptid, v_deptname
FROM departments
WHERE manager_id = 200;
SELECT count(*)
INTO v_emps
FROM employees
WHERE department_id = v_deptid;
ELSE
SELECT department_id,department_name
INTO v_deptid, v_deptname
FROM departments
WHERE manager_id = 100;
SELECT count(*)
INTO v_emps
FROM employees
WHERE department_id = v_deptid;
END CASE;
DBMS_OUTPUT.PUT_LINE('You are workingin the ' || v_deptname || ' department. There are ' ||v_emps || 'employees inthis department');
END;
/
SQL> /
You are working in theExecutive department. There are 3 employees in this
department
PL/SQL procedure successfullycompleted.
三、关于NULL值的处理
NULL值在PL/SQL中有一些特殊的属性:
a. 在简单的比较运算表达式里如果有NULL值参与运算,最终的结果将表现为NULL值;
b. 在逻辑运算中如果出现了 NOT NULL,则结果还是NULL,只有写成IS NULL或者是IS NOT NULL,才能得到TRUE或者FALSE的值;
c. IF条件判断语句中只有结果为TRUE时,才执行THEN后面的语句,如果结果为NULL或者FASLE,则不会执行
d. NULL值在PL/SQL中还可以单独成为一条语句,用来表示什么都不做,例如:
IF conditions THEN
Dosome thing;
ELSE
NULL;
使用NULL语句的主要有:
1. 增强程序的可读性。
2. 在标签后面使用NULL。
标签的用法后文会详解,这里先举个小例子:
DECLARE
...
BEGIN
IFconditions THEN
GOTO LastPoint
-- GOTO表示执行到这一步时,直接跳转到标签LastPoint所在的位置。
ENDIF
...
<<LastPoint>>
--标签LastPoint的后面应该有语句,但在生产环境中经常会碰到标签后面不做任何操作的情况
--使用NULL;语句,可以既满足语法规则,又不做任何操作。
NULL;
END;
四、条件判断中的逻辑关系
1. 逻辑运算符AND,OR和NOT
在进行条件判断时可以使用逻辑运算符AND, OR 和NOT,当布尔值和逻辑运算符组合起来后会形成各种逻辑关系:
2. 短路现象
短路操作是指在逻辑判断中只用判断一部分条件而无需判断整个条件的运算方式。如果逻辑运算符是AND,则AND前面的条件判断为FALSE后,就不继续判断AND后面的条件了;如果逻辑运算符是OR,则OR前面的条件判断为真后,就不继续判断OR后面的条件了。