Oracle  11g从入门到精通(第2版) (软件开发视频大讲堂)
上QQ阅读APP看书,第一时间看更新

5.3 流程控制语句

视频讲解:光盘\TM\lx\5\流程控制语句.mp4

结构控制语句是所有过程性程序设计语言的关键,因为只有能够进行结构控制才能灵活地实现各种操作和功能,PL/SQL也不例外,其主要控制语句如表5.3所示。

表5.3 PL/SQL控制语句列表

若要在PL/SQL中实现控制程序的执行流程和实现复杂的业务逻辑计算,就必须使用流程控制语句,因为只有能够进行结构控制才能灵活地实现各种复杂操作和功能,PL/SQL中的流程控制语句主要包括选择语句、循环语句两大类,下面将对这两种控制语句进行详细讲解。

5.3.1 选择语句

选择语句也称之为条件语句,它的主要作用是根据条件的变化选择执行不同的代码,主要分为以下4种语句。

1.IF…THEN语句

IF…THEN语句是选择语句中最简单的一种形式,它只做一种情况或条件的判断,其语法格式如下:

        if < condition_expression> then
          plsql_sentence
        end if;

condition_expression:表示一个条件表达式,当其值为true时,程序会执行IF下面的PL/SQL语句(即plsql_sentence语句);如果其值为false,则程序会跳过IF下面的语句而直接执行end if后面的语句。

plsql_sentence:当condition_expression表达式的值为true时,要执行的PL/SQL语句。

【例5.11】 定义两个字符串变量,然后赋值,接着使用IF…THEN语句比较两个字符串变量的长度,并输出比较结果,代码如下(实例位置:光盘\TM\sl\5\5)

        SQL> set serveroutput on
        SQL> declare
          2   var_name1 varchar2(50);                        --定义两个字符串变量
          3   var_name2 varchar2(50);
          4  begin
          5   var_name1:='East';                             --给两个字符串变量赋值
          6   var_name2:='xiaoke';
          7   if length(var_name1)<length(var_name2)then     --比较两个字符串的长度大小
          8     /*输出比较后的结果*/
          9     dbms_output.put_line(’字符串“'||var_name1||'”的长度比字符串“'||var_name2||'”的长度小’);
         10   end if;
         11  end;
         12  /                                               --执行代码

本例运行结果如图5.5所示。

图5.5 使用if…then语句比较两个字符串长度

在上面的例子中,字符串“East”的长度(4)肯定小于字符串“xiaoke”的长度(6),所以if后面的条件表达式的值为true,这样程序就会执行if下面的PL/SQL语句。

如果IF后面的条件表达式存在“并且”、“或者”、“非”等逻辑运算,则可以使用“and”、“or”、“not”等逻辑运算符。另外,如果要判断IF后面的条件表达式的值是否为空值,则需要在条件表达式中使用“is”和“null”关键字,比如下面的代码:

        if last_name is null then
        …;
        end if;

2.IF…THEN…ELSE语句

在编写程序的过程中,IF…THEN…ELSE语句是最常用到的一种选择语句,它可以实现判断两种情况,只要if后面的条件表达式为false,程序就会执行else语句下面的PL/SQL语句。其语法格式如下:

        if < condition_expression> then
          plsql_sentence1;
        else
          plsql_sentence2;
        end if;

condition_expression:表示一个条件表达式,若该条件表达式的值为true,则程序执行if下面的PL/SQL语句,即plsql_sentence1语句;否则,程序将执行else下面的PL/SQL语句,即plsql_sentence2语句。

plsql_sentence1:IF语句的表达式值为true时,要执行的PL/SQL语句。

plsql_sentence2:IF语句的表达式值为false时,要执行的PL/SQL语句。

【例5.12】 通过IF…ELSE语句实现只有年龄大于等于56岁,才可以申请退休的功能,否则程序会提示不可以申请退休,代码如下(实例位置:光盘\TM\sl\5\6)

        SQL> set serveroutput on
        SQL> declare
          2   age int:=55;                                                 --定义整形变量并赋值
          3  begin
          4   if age>=56 then                                             --比较年龄是否大于56岁
          5     dbms_output.put_line(’您可以申请退休了!');              --输出可以退休信息
          6   else
          7     dbms_output.put_line(’您小于56岁,不可以申请退休了!');   --输出不可退休信息
          8   end if;
          9  end;
         10  /

本例运行结果如图5.6所示。

图5.6 IF…THEN…ELSE语句判断是否可以退休

3.IF…THEN…ELSIF语句

IF…THEN…ELSIF语句实现了多分支判断选择,它使程序的判断选择条件更加丰富,更加多样化。该语句中的哪个判断分支的表达式为true,那么程序就会执行其下面对应的PL/SQL语句,其语法格式如下:

        if < condition_expression1 > then
          plsql_sentence_1;
        elsif < condition_expression2 > then
          plsql_sentence_2;
        …
        else
          plsql_sentence_n;
        end if;

condition_expression1:第一个条件表达式,若其值为false,则程序继续判断condition_expression2表达式。

condition_expression2:第二个条件表达式,若其值false,则程序继续判断下面的elsif语句后面的表达式;若再没有“elsif”语句,则程序将执行else语句下面的PL/SQL语句。

plsql_sentence_1:第一个条件表达式的值为true时,要执行的PL/SQL语句。

plsql_sentence_2:第二个条件表达式的值为true时,要执行的PL/SQL语句。

plsql_sentence_n:当其上面所有的条件表达式的值都为false时,要执行的PL/SQL语句。

【例5.13】 指定一个月份数值,然后使用IF…THEN…ELSIF语句判断它所属的季节,并输出季节信息,代码如下(实例位置:光盘\TM\sl\5\7)

        SQL> set serveroutput on
        SQL> declare

          2   month int:=10;                           --定义整形变量并赋值
          3  begin
          4   if month>=0 and month<=3  then           --判断春季
          5     dbms_output.put_line(’这是春季’);
          6   elsif  month>=4 and month<=6 then         --判断夏季
          7     dbms_output.put_line(’这是夏季’);
          8   elsif  month>=7 and month<=9  then       --判断秋季
          9     dbms_output.put_line(’这是秋季’);
         10   elsif  month>=10 and month<=12 then      --判断冬季
         11     dbms_output.put_line(’这是冬季’);
         12   else
         13     dbms_output.put_line(’对不起,月份不合法!');
         14   end if;
         15  end;
         16  /

本例运行结果如图5.7所示。

图5.7 使用if…then…elsif语句判断季节

注意

在IF…THEN…ELSIF语句中,多个条件表达式之间不能存在逻辑上的冲突,否则程序将判断出错!

4.case语句

从Oracle 9i以后,PL/SQL也可以像其他编程语言一样使用CASE语句,CASE语句的执行方式与IF…THEN…ELSIF语句十分相似。在CASE关键字的后面有一个选择器,它通常是一个变量,程序就从这个选择器开始执行,接下来是WHEN子句,并且在WHEN关键字的后面是一个表达式,程序将根据选择器的值去匹配每个WHEN子句中的表达式的值,从而实现执行不同的PL/SQL语句的功能,其语法格式如下:

        case < selector>
          when <expression_1> then plsql_sentence_1;
          when <expression_2> then plsql_sentence_2;
        …
          when <expression_n> then plsql_sentence_n;
          [else plsql_sentence; ]
        end case;

selector:一个变量,用来存储要检测的值,通常称之为选择器。该选择器的值需要与WHEN子句中的表达式的值进行匹配。

expression_1:第一个WHEN子句中的表达式,这种表达式通常是一个常量,当选择器的值等于该表达式的值时,程序将执行plsql_sentence_1语句。

expression_2:第二个WHEN子句中的表达式,它通常也是一个常量,当选择器的值等于该表达式的值时,程序将执行plsql_sentence_2语句。

expression_n:第n个WHEN子句中的表达式,它通常也是一个常量,当选择器的值等于该表达式的值时,程序将执行plsql_sentence_n语句。

plsql_sentence:一个PL/SQL语句,当没有与选择器匹配的WHEN常量时,程序将执行该PL/SQL语句,其所在的ELSE语句是一个可选项。

【例5.14】 指定一个季度数值,然后使用CASE语句判断它所包含的月份信息并输出,代码如下(实例位置:光盘\TM\sl\5\8)

        SQL> set serveroutput on
        SQL> declare
          2   season int:=3;                                   --定义整形变量并赋值
          3   aboutInfo varchar2(50);                          --存储月份信息
          4  begin
          5   case season                                      --判断季度
          6     when 1 then                                    --若是1季度
          7       aboutInfo:=season||’季度包括1,2,3月份’;
          8     when 2 then                                    --若是2季度
          9       aboutInfo:=season||’季度包括4,5,6月份’;
         10     when 3 then                                    --若是3季度
         11       aboutInfo:=season||’季度包括7,8,9月份’;
         12     when 4 then                                    --若是4季度
         13       aboutInfo:=season||’季度包括10,11,12月份’;
         14     else                                           --若季度不合法
         15       aboutInfo:=season||’季节不合法’;
         16   end case;
         17   dbms_output.put_line(aboutinfo);                 --输出该季度所包含的月份信息
         18  end;
         19  /

本例运行结果如图5.8所示。

图5.8 使用case判断某个季度所包含的月份

技巧

在进行多种情况判断时,建议使用CASE语句替换IF…THEN…ELSIF语句,因为CASE语句的语法更加简洁明了,易于阅读。

5.3.2 循环语句

当程序需要反复执行某一操作时,就必须使用循环结构。PL/SQL中的循环语句主要包括LOOP语句、WHILE语句和FOR语句3种,本节将对这3种循环语句分别进行介绍。

1.LOOP语句

LOOP语句会先执行一次循环体,然后再判断“EXIT WHEN”关键字后面的条件表达式的值是true还是false,如果是true,则程序会退出循环体,否则程序将再次执行循环体,这样就使得程序至少能够执行一次循环体,它的语法格式如下:

        loop
          plsql_sentence;
          exit when end_condition_ exp
        end loop;

plsql_sentence:循环体中的PL/SQL语句,可能是一条语句,也可能是多条,这是循环体的核心部分,这些PL/SQL语句至少会被执行一遍。

end_condition_ exp:循环结束条件表达式,当该表达式的值为true时,程序会退出循环体,否则程序将再次执行循环体。

【例5.15】 使用LOOP语句求得前100个自然数的和,并输出到屏幕,代码如下(实例位置:光盘\TM\sl\5\9)

        SQL> set serveroutput on
        SQL> declare
          2   sum_i int:=0;                                           --定义整数变量,存储整数和
          3   i int:=0;                                               --定义整数变量,存储自然数
          4  begin
          5   loop                                                    --循环累加自然数
          6     i:=i+1;                                               --得出自然数
          7     sum_i:=sum_i+i;                                       --计算前n个自然数的和
          8     exit when i=100;                                      --当循环100次时,程序退出循环体
          9   end loop;
         10   dbms_output.put_line(’前100个自然数的和是:'||sum_i);   --计算前100个自然数的和
         11  end;
         12  /

本例运行结果如图5.9所示。

图5.9 求得前100个自然数的和

在上面的代码中,每一次循环i的值都会自增1,变成一个新的自然数,然后使用sum_i这个变量存储前n个自然数的和,当i的值为100时,结束循环。

2.WHILE语句

WHILE语句根据它的条件表达式的值执行零次或多次循环体,在每次执行循环体之前,首先要判断条件表达式的值是否为true,若为true,则程序执行循环体;否则退出WHILE循环,然后继续执行WHILE语句后面的其他代码,其语法格式如下。

        while condition_expression loop
          plsql_sentence;
        end loop;

condition_expression:表示一个条件表达式,当其值为true时,程序执行循环体,否则程序退出循环体,程序每次在执行循环体之前,都要首先判断该表达式的值是否为true。

plsql_sentence:循环体内的PL/SQL语句。

【例5.16】 使用while语句求得前100个自然数的和,并输出到屏幕,代码如下(实例位置:光盘\TM\sl\5\10)

        SQL> set serveroutput on
        SQL> declare
          2   sum_i int:=0;                                           --定义整数变量,存储整数和
          3   i int:=0;                                               --定义整数变量,存储自然数
          4  begin
          5   while i<=99 loop                                       --当i的值等于100时,程序退出while循环
          6     i:=i+1;                                               --得出自然数
          7     sum_i:=sum_i+i;                                       --计算前n个自然数的和
          8   end loop;
          9   dbms_output.put_line(’前100个自然数的和是:'||sum_i);   --计算前100个自然数的和
         10  end;
         11  /

本例运行效果如图5.10所示。

图5.10 求得前100个自然数的和

在上面的代码中,只要i的值小于100,程序就会反复地执行循环体,这样i的值就会自增1,从而得到一个新的自然数,然后使用sum_i这个变量存储前n个自然数的和,当i的值增长到100时,条件表达式的值就为false,导致while循环结束。

3.FOR语句

FOR语句是一个可预置循环次数的循环控制语句,它有一个循环计数器,通常是一个整型变量,通过这个循环计数器来控制循环执行的次数。该计数器可以从小到大进行记录,也可以相反,从大到小进行记录。另外,该计数器值的合法性由上限值和下限值控制,若计数器值在上限值和下限值的范围内,则程序执行循环;否则,终止循环。其语法格式如下。

        for variable_ counter_name in [reverse] lower_limit..upper_limit loop
          plsql_sentence;
        end loop;

variable_ counter_name:表示一个变量,通常为整数类型,用来作为计数器。默认情况下计数器的值会循环递增,当在循环中使用REVERSE关键字时,计数器的值会随循环递减。

lower_limit:计数器的下限值,当计数器的值小于下限值时,程序终止FOR循环。

upper_limit:计数器的上限值,当计数器的值大于上限值时,程序终止FOR循环。

plsql_sentence:表示PL/SQL语句,作为for语句的循环体。

【例5.17】 使用FOR语句求得前100个自然数中偶数之和,并输出到屏幕,代码如下(实例位置:光盘\TM\sl\5\11)

        SQL> set serveroutput on
        SQL> declare
          2   sum_i int:=0;                     --定义整数变量,存储整数和
          3  begin
          4   for i in reverse 1..100 loop      --遍历前100个自然数
          5     if mod(i,2)=0 then              --判断是否为偶数
          6       sum_i:=sum_i+i; -             --计算偶数和
          7     end if;
          8   end loop;
          9   dbms_output.put_line(’前100个自然数中偶数之和是:'||sum_i);
         10  end;
         11  /

本例运行结果如图5.11所示。

图5.11 计算前100个自然数中偶数之和

在上面的FOR语句中,由于使用了关键字REVERSE,表示计数器i的值为递减状态,即i的初始值为100,随着每次递减1,最后一次for循环时i的值变为1。如果在for语句中不使用关键字REVERSE,则表示计数器i的值为递增状态,即i的初始值为1。

4.GOTO语句

GOTO语句的语法是:

        GOTO label;

这是个无条件转向语句。当执行GOTO语句时,控制程序会立即转到由标签标识的语句。其中,label是在PL/SQL中定义的符号。标签使用双箭头括号(<< >>)括起来的。

【例5.18】 GOTO语句实例,代码如下。

        … --程序其他部分
        <<goto_mark>>                        --定义了一个转向标签goto_mark
        … --程序其他部分
        IF no>98050 THEN
            GOTO goto_mark;                  --如果条件成立则转向goto_mark继续执行
        … --程序其他部分

在使用GOTO语句时需要十分谨慎。不必要的GOTO语句会使程序代码复杂化,容易出错,而且难以理解和维护。事实上,几乎所有使用GOTO的语句都可以使用其他的PL/SQL控制结构(如循环或条件结构)来重新进行编写。