编写控制结构
一.条件分支语句
条件分支语句用于依据特定情况选择要执行的操作。在Oracle 9i之前执行条件分支操作都需要使用IF语句来完成,并且PL/SQL提供了三种条件分支语句:IF-THEN,IF-THEN-ELSE,IF-THEN-ELSEIF。
语法:
IF condition THEN
statements;
[ELSIF condition THEN
statements;]
[ELSE
statements;]
END IF;
当使用条件分支语句时,不仅可以使用IF语句进行简单条件判断,而且还可以使用IF语句进行二重分支和多重分支判断。
注意,ELSIF和END IF可能与其他语言的语法有所不同,ELSIF为一个单词,而END IF则是两个单词。
(1) 简单条件判断
简单条件判断用于执行单一条件判断。如果满足特定条件,则会执行相应操作;如果不满足条件,则退出条件分支语句。简单条件判断是使用IF-THEN语句来完成的。
示例:
DECLARE
v_sal NUMBER(6,2);
BEGIN
SELECT sal INTO v_sal FROM emp
WHERE LOWER(ename) = LOWER('&&name');
IF v_sal < 2000 THEN
UPDATE emp SET sal = v_sal + 200
WHERE LOWER(ename) = LOWER('&name');
END IF;
END;
输出:
原值 5: WHERE LOWER(ename) = LOWER('&&name');
新值 5: WHERE LOWER(ename) = LOWER('SCOTT');
原值 8: WHERE LOWER(ename) = LOWER('&name');
新值 8: WHERE LOWER(ename) = LOWER('SCOTT');
PL/SQL 过程已成功完成。
(2) 二重条件分支
二重条件分支是指根据条件来选择两种可能性。当使用二重条件分支时,如果满足条件,则执行一组操作;如果不满足条件,则执行另外一组操作。二重条件分支是使用IF…THEN…ELSE来完成的。
DECLARE
v_comm NUMBER(6,2);
BEGIN
SELECT comm INTO v_comm FROM emp
WHERE empno = &&no;
IF v_comm <> 0 THEN
UPDATE emp SET comm = v_comm + 100
WHERE empno = &no;
ELSE
UPDATE emp SET comm = 200
WHERE empno = &no;
END IF;
END;
输出:
原值 5: WHERE empno = &&no;
新值 5: WHERE empno = 7934;
原值 8: WHERE empno = &no;
新值 8: WHERE empno = 7934;
原值 11: WHERE empno = &no;
新值 11: WHERE empno = 7934;
PL/SQL 过程已成功完成。
(3) 多重条件分支
多重条件分支用于执行最复杂的条件分支操作。当使用多重条件分支时,如果满足第一个条件,则执行第一种操作;如果不满足第一个条件,则检查是否满足第二个条件,如果满足第二个条件,则执行第二种操作;如果不满足第二个条件,则检查是否满足第三个条件,依此类推。
示例:
undefine no
DECLARE
v_job VARCHAR2(10);
v_sal NUMBER(6,2);
BEGIN
SELECT job,sal INTO v_job,v_sal
FROM emp WHERE empno = &&no;
IF v_job = 'PRESIDENT' THEN
UPDATE emp SET sal = v_sal + 1000 WHERE empno = &no;
ELSIF v_job = 'MANAGER' THEN
UPDATE emp SET sal = v_sal + 500 WHERE empno = &no;
ELSE
UPDATE emp SET sal = v_sal + 200 WHERE empno = &no;
END IF;
END;
输出:
原值 6: FROM emp WHERE empno = &&no;
新值 6: FROM emp WHERE empno = 7782;
原值 8: UPDATE emp SET sal = v_sal + 1000 WHERE empno = &no;
新值 8: UPDATE emp SET sal = v_sal + 1000 WHERE empno = 7782;
原值 10: UPDATE emp SET sal = v_sal + 500 WHERE empno = &no;
新值 10: UPDATE emp SET sal = v_sal + 500 WHERE empno = 7782;
原值 12: UPDATE emp SET sal = v_sal + 200 WHERE empno = &no;
新值 12: UPDATE emp SET sal = v_sal + 200 WHERE empno = 7782;
PL/SQL 过程已成功完成。
二.CASE语句
(1) 在CASE语句中使用单一选择符进行等值比较
当使用CASE语句执行多重条件分支时,如果条件选择符完全相同,并且条件表达式为相等条件选择,那么可以选择使用单一条件选择符进行等值比较。
语法:
CASE selector
WHEN expression1 THEN sequence_of_statements1;
WHEN expression2 THEN sequence_of_statements2;
…
WHEN expression_of_statementsN;
[ELSE sequence_of_statementsN+1;]
END CASE;
l selector:用于指定条件选择符
l expression:用于指定条件值的表达式
l sequence_of_statement:用于指定要执行的条件操作
如果设置的所有条件都不满足,则会执行ELSE后的语句。
注意,为了避免CASE_NOT_FOUND例外,在编写CASE语句时应该带有ELSE子句。
示例:
DECLARE
v_deptno emp.deptno%TYPE;
BEGIN
v_deptno := &no;
CASE v_deptno
WHEN 10 THEN
UPDATE emp SET comm = 100 WHERE deptno = v_deptno;
WHEN 20 THEN
UPDATE emp SET comm = 80 WHERE deptno = v_deptno;
WHEN 30 THEN
UPDATE emp SET comm = 50 WHERE deptno = v_deptno;
ELSE
dbms_output.put_line('不存在该部门');
END CASE;
END;
输出:
原值 4: v_deptno := &no;
新值 4: v_deptno := 20;
PL/SQL 过程已成功完成。
(2) 在CASE语句中使用多种条件比较
当使用单一条件选择符进行等值比较时,可以使用CASE selector语句来实现。如果包含有多种条件进行不等比较,那么必须在WHEN子句中指定比较条件。
语法:
CASE
WHEN search_condition1 THEN sequence_of_statements1;
WHEN search_condition2 THEN sequence_of_statements2;
…
WHEN search_conditionN THEN sequence_of_statementsN;
[ELSE sequence_of_statementsN+1;]
END CASE;
l search_condition:用于指定不同比较条件
l sequence_of_statement:用于指定当满足特定条件时要执行的操作
如果设置的所有条件都得不到满足,则会执行ELSE后的语句。
注意,为了避免CASE_NOT_FOUND例外,在编写CASE语句时应该带有ELSE子句。
示例:
DECLARE
v_sal emp.sal%TYPE;
v_ename emp.ename%TYPE;
BEGIN
SELECT ename,sal INTO v_ename,v_sal
FROM emp WHERE empno = &no;
CASE
WHEN v_sal < 1000 THEN
UPDATE emp SET comm = 100 WHERE ename = v_ename;
WHEN v_sal < 2000 THEN
UPDATE emp SET comm = 80 WHERE ename = v_ename;
WHEN v_sal < 6000 THEN
UPDATE emp SET comm = 50 WHERE ename = v_ename;
END CASE;
END;
输出:
原值 6: FROM emp WHERE empno = &no;
新值 6: FROM emp WHERE empno = 7788;
PL/SQL 过程已成功完成。
三.循环语句
为了在编写的PL/SQL块中重复执行一条语句或者一组语句,可以使用循环控制结构。编写循环控制结构时,用户可以使用基本循环、WHILE循环和FOR循环等三种类型的循环语句。
(1) 基本循环
在PL/SQL中最简单格式的循环语句是基本循环语句,这种循环语句以LOOP开始,以END LOOP结束。
语法:
LOOP
statement1;
…
EXIT [WHEN condition];
END LOOP;
当使用基本循环时,无论是否满足条件,语句至少会被执行一次。当condition为TRUE时,会退出循环,并执行END LOOP后的相应操作。
注意,当编写基本循环时,一定要包含EXIT语句,否则PL/SQL块会陷入死循环;另外当使用基本循环时,应该定义循环控制变量,并且在循环体内修改循环控制变量的值。
示例:
CREATE TABLE temp(cola INT);
DECLARE
i INT := 1;
BEGIN
LOOP
INSERT INTO temp VALUES(i);
EXIT WHEN i = 10;
i := i + 1;
END LOOP;
END;
输出:
PL/SQL 过程已成功完成。
(2) WHILE循环
基本循环至少要执行一次循环体内的语句,而对于WHILE循环来说,只有条件为TRUE时,才会执行循环体内的语句。WHILE循环以WHILE…LOOP开始,以END LOOP结束。
语法:
WHILE condition LOOP
statement1;
statement2;
…
END LOOP;
当condition为TRUE时,PL/SQL执行器会执行循环体内的语句;而当condition为FALSE或NULL时,会退出循环,并执行END LOOP后的语句。
注意,当使用WHILE循环时,应该定义循环控制变量,并在循环体内改变循环控制变量的值。
示例:
DECLARE
i INT := 1;
BEGIN
WHILE i <= 10 LOOP
DELETE temp WHERE cola = i;
i := i + 1;
END LOOP;
END;
输出:
PL/SQL 过程已成功完成。
(3) FOR循环
当使用基本循环或WHILE循环时,需要定义循环控制变量,并且循环控制变量不仅可以使用NUMBER类型,也可以使用其他数据类型;而当使用FOR循环时,Oracle会隐含定义循环控制变量。
语法:
FOR counter in [PEVERSE]
lower_bound .. upper_bound LOOP
statement1;
satement2;
…
END LOOP;
l counter:是循环控制变量,并且该变量由Oracle隐含定义,不需要显式定义
l lower_bound和upper_bound:分别对应于循环控制变量的下界值和上界值。
默认情况下,当使用FOR循环时,每次循环时循环控制变量会自动增一;如果指定PEVERSE选项,那么每次循环时循环控制变量会自动减一。
示例:
BEGIN
FOR i IN 1..10 LOOP
INSERT INTO temp VALUES(i);
END LOOP;
END;
输出:
PL/SQL 过程已成功完成。
(4) 嵌套循环和标号
嵌套循环是指在一个循环语句之中嵌入另一个循环语句,而标号(Label)则用于标记嵌套块或嵌套循环。通过在嵌套循环中使用标号,可以区分内层循环和外层循环,并且可以在内层循环中直接退出外层循环。在编写PL/SQL块时,可以使用<<label_name>>定义标号。
示例:
DECLARE
result INT;
BEGIN
<<outer>>
FOR i IN 1..100 LOOP
<<inter>>
FOR j IN 1..100 LOOP
result := i * j;
EXIT outer WHEN result = 1000;
EXIT WHEN result = 500;
END LOOP inner;
dbms_output.put_line(result);
END LOOP outer;
dbms_output.put_line(result);
END;
四.顺序控制语句
PL/SQL不仅提供了条件分支语句和循环控制语句,而且还提供了顺序控制语句GOTO和NULL。但与IF,CASE和LOOP语句不同,GOTO语句和NULL语句,一般情况下不要使用。
(1) GOTO
GOTO语句用于跳转到特定标号处去执行语句。
注意,因为使用GOTO语句会增加程序的复杂性,并且使得应用程序可读性变差。
语法:
GOTO label_name;
l label_name:是已经定义的标号名。
注意,当使用GOTO跳转到特定标号时,标号后至少要包含一条可执行语句。
示例:
DECLARE
i INT := 1;
BEGIN
LOOP
INSERT INTO temp VALUES(i);
IF i = 10 THEN
GOTO end_loop;
END IF;
i := i + 1;
END LOOP;
<<end_loop>>
dbms_output.put_line('循环结束');
END;
输出:
循环结束
PL/SQL 过程已成功完成。
(2) NULL
NULL语句不会执行任何操作,并且会直接将控制传递到下一条语句。使用NULL语句的主要好处是可以提高PL/SQL程序的可读性。
示例:
DECLARE
v_sal emp.sal%TYPE;
v_ename emp.ename%TYPE;
BEGIN
SELECT ename,sal INTO v_ename,v_sal
FROM emp WHERE empno = &no;
IF v_sal < 3000 THEN
UPDATE emp SET comm = sal*0.1 WHERE ename = v_ename;
ELSE
NULL;
END IF;
END;
输出:
原值 6: FROM emp WHERE empno = &no;
新值 6: FROM emp WHERE empno = 7782;
PL/SQL 过程已成功完成。