[推荐]ORACLE PL/SQL编程详解之三:

PL/SQL流程控制语句(不给规则,不成方圆)


——通过知识共享树立个人品牌。



继上五篇:

   [顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功)


   [推荐]ORACLE PL/SQL编程之四:把游标说透(不怕做不到,只怕想不到)

 

     [推荐]ORACLE PL/SQL编程之五:异常错误处理(知已知彼、百战不殆)




   ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!) 

 

      ORACLE PL/SQL编程之八:把触发器说透 


接下来再次介绍PL/SQL的基础篇:PL/SQL流程控制语句,还望大家继续支持与推荐~!


 


本篇主要内容如下:

3.1  条件语句

3.2  CASE 表达式

3.3  循环

3.4GOTO

3.5语句


 



介绍PL/SQL的流程控制语句, 包括如下三类:

 

l 控制语句: IF 语句

l 循环语句: LOOP语句, EXIT语句

l 顺序语句: GOTO语句, NULL语句


3.1  条件语句

 


IF 
    
  < 
  布尔表达式 
  > 
    
  THEN 
  
  PL 
  / 
  SQL 和 SQL语句
 
  END 
    
  IF 
  ;
 
  -- 
  --------------------- 
  
 
  IF 
    
  < 
  布尔表达式 
  > 
    
  THEN 
  
  PL 
  / 
  SQL 和 SQL语句
 
  ELSE 
  
  其它语句
 
  END 
    
  IF 
  ;
 
  -- 
  --------------------- 
  
 
  IF 
    
  < 
  布尔表达式 
  > 
    
  THEN 
  
  PL 
  / 
  SQL 和 SQL语句
ELSIF  
  < 
   其它布尔表达式 
  > 
    
  THEN 
  
  其它语句
ELSIF  
  < 
   其它布尔表达式 
  > 
    
  THEN 
  
  其它语句
 
  ELSE 
  
  其它语句
 
  END 
    
  IF 
  ;


 

 

提示: ELSIF 不能写成 ELSEIF


例1:

DECLARE 
  
    v_empno  employees.employee_id 
  % 
  TYPE : 
  =& 
  empno;
    V_salary employees.salary 
  % 
  TYPE;
    V_comment  
  VARCHAR2 
  ( 
  35 
  );
 
  BEGIN 
  
    
  SELECT 
   salary  
  INTO 
   v_salary  
  FROM 
   employees 
    
  WHERE 
   employee_id  
  = 
   v_empno;
    
  IF 
   v_salary  
  < 
    
  1500 
    
  THEN 
  
       V_comment: 
  = 
    
  ' 
  太少了,加点吧~! 
  ' 
  ;
   ELSIF v_salary  
  < 
  3000 
    
  THEN 
  
      V_comment: 
  = 
    
  ' 
  多了点,少点吧~! 
  ' 
  ;
    
  ELSE 
  
      V_comment: 
  = 
    
  ' 
  没有薪水~! 
  ' 
  ;
    
  END 
    
  IF 
  ;
   DBMS_OUTPUT.PUT_LINE(V_comment);
   exception
      
  when 
   no_data_found  
  then 
  
        DBMS_OUTPUT.PUT_LINE( 
  ' 
  没有数据~! 
  ' 
  );
      
  when 
   others  
  then 
  
        DBMS_OUTPUT.PUT_LINE(sqlcode  
  || 
    
  ' 
  --- 
  ' 
    
  || 
   sqlerrm);        
 
  END 
  ;

 

例2:

 

DECLARE 
  
   v_first_name   
  VARCHAR2 
  ( 
  20 
  );
   v_salary  
  NUMBER 
  ( 
  7 
  , 
  2 
  );
 
  BEGIN 
  
    
  SELECT 
   first_name, salary  
  INTO 
   v_first_name, v_salary  
  FROM 
   employees
    
  WHERE 
   employee_id  
  = 
    
  & 
  emp_id;
   DBMS_OUTPUT.PUT_LINE(v_first_name 
  || 
  ' 
  雇员的工资是 
  ' 
  || 
  v_salary);
    
  IF 
   v_salary  
  < 
    
  10000 
    
  THEN 
  
      DBMS_OUTPUT.PUT_LINE( 
  ' 
  工资低于10000 
  ' 
  );
    
  ELSE 
  
       
  IF 
    
  10000 
    
  <= 
   v_salary  
  AND 
   v_salary  
  < 
    
  20000 
    
  THEN 
  
         DBMS_OUTPUT.PUT_LINE( 
  ' 
  工资在10000到20000之间 
  ' 
  );
       
  ELSE 
  
         DBMS_OUTPUT.PUT_LINE( 
  ' 
  工资高于20000 
  ' 
  );
       
  END 
    
  IF 
  ;
    
  END 
    
  IF 
  ;
 
  END 
  ;

 

 

例3:

DECLARE 
   
   v_first_name   
   VARCHAR2 
   ( 
   20 
   );
   v_hire_date DATE;
   v_bonus  
   NUMBER 
   ( 
   6 
   , 
   2 
   );
 
   BEGIN 
   
    
   SELECT 
    first_name, hire_date  
   INTO 
    v_first_name, v_hire_date  
   FROM 
    employees
    
   WHERE 
    employee_id  
   = 
     
   & 
   emp_id;
    
   IF 
    v_hire_date  
   > 
    TO_DATE( 
   ' 
   01-1月-90 
   ' 
   )  
   THEN 
   
      v_bonus : 
   = 
     
   800 
   ;
   ELSIF v_hire_date  
   > 
    TO_DATE( 
   ' 
   01-1月-88 
   ' 
   )  
   THEN 
   
      v_bonus : 
   = 
     
   1600 
   ;
    
   ELSE 
   
      v_bonus : 
   = 
     
   2400 
   ;
    
   END 
     
   IF 
   ;
   DBMS_OUTPUT.PUT_LINE(v_first_name 
   || 
   ' 
   雇员的雇佣日期是 
   ' 
   || 
   v_hire_date
                                     
   || 
   ' 
   、奖金是 
   ' 
   || 
   v_bonus);
 
   END 
   ;

 

3.2  CASE 表达式

 

-- 
  -------格式一--------- 
  
 
  CASE 
   条件表达式
   
  WHEN 
   条件表达式结果1  
  THEN 
   
     语句段1
   
  WHEN 
   条件表达式结果2  
  THEN 
  
     语句段2
  ......
   
  WHEN 
   条件表达式结果n  
  THEN 
  
     语句段n
   
  [ 
  ELSE 条件表达式结果 
  ] 
  
 
  END 
  ;
 
  -- 
  -------格式二--------- 
  
 
  CASE 
   
   
  WHEN 
   条件表达式1  
  THEN 
  
     语句段1
   
  WHEN 
   条件表达式2  
  THEN 
  
     语句段2
  ......
   
  WHEN 
   条件表达式n  
  THEN 
   
     语句段n
   
  [ 
  ELSE 语句段 
  ] 
  
 
  END 
  ;

例4:

 


DECLARE 
  
  V_grade  
  char 
  ( 
  1 
  ) : 
  = 
    
  UPPER 
  ( 
  ' 
  &p_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 
  ;
  DBMS_OUTPUT.PUT_LINE( 
  ' 
  Grade: 
  ' 
  || 
  v_grade 
  || 
  ' 
    Appraisal:  
  ' 
  || 
   v_appraisal);
 
  END 
  ;


 

 

例5:

 

DECLARE 
  
   v_first_name employees.first_name 
  % 
  TYPE;
   v_job_id employees.job_id 
  % 
  TYPE;
   v_salary employees.salary 
  % 
  TYPE;
   v_sal_raise  
  NUMBER 
  ( 
  3 
  , 
  2 
  );
 
  BEGIN 
  
    
  SELECT 
   first_name,   job_id,   salary  
  INTO 
  
          v_first_name, v_job_id, v_salary
    
  FROM 
   employees  
  WHERE 
   employee_id  
  = 
    
  & 
  emp_id;
    
  CASE 
  
       
  WHEN 
   v_job_id  
  = 
    
  ' 
  PU_CLERK 
  ' 
    
  THEN 
  
          
  IF 
   v_salary  
  < 
    
  3000 
    
  THEN 
   v_sal_raise : 
  = 
   . 
  08 
  ;
          
  ELSE 
   v_sal_raise : 
  = 
   . 
  07 
  ;
          
  END 
    
  IF 
  ;
       
  WHEN 
   v_job_id  
  = 
    
  ' 
  SH_CLERK 
  ' 
    
  THEN 
  
          
  IF 
   v_salary  
  < 
    
  4000 
    
  THEN 
   v_sal_raise : 
  = 
   . 
  06 
  ;
          
  ELSE 
   v_sal_raise : 
  = 
   . 
  05 
  ;
          
  END 
    
  IF 
  ;
       
  WHEN 
   v_job_id  
  = 
    
  ' 
  ST_CLERK 
  ' 
    
  THEN 
  
          
  IF 
   v_salary  
  < 
    
  3500 
    
  THEN 
   v_sal_raise : 
  = 
   . 
  04 
  ;
          
  ELSE 
   v_sal_raise : 
  = 
   . 
  03 
  ;
          
  END 
    
  IF 
  ;
       
  ELSE 
  
         DBMS_OUTPUT.PUT_LINE( 
  ' 
  该岗位不涨工资:  
  ' 
  || 
  v_job_id);
    
  END 
    
  CASE 
  ;
   DBMS_OUTPUT.PUT_LINE(v_first_name 
  || 
  ' 
  的岗位是 
  ' 
  || 
  v_job_id
                                     
  || 
  ' 
  、的工资是 
  ' 
  || 
  v_salary
                                     
  || 
  ' 
  、工资涨幅是 
  ' 
  || 
  v_sal_raise);
 
  END 
  ;

 


3.3  循环

简单循环

  

LOOP
      要执行的语句;
       
  EXIT 
    
  WHEN 
    
  < 
  条件语句 
  > 
    
  -- 
  条件满足,退出循环语句 
  
 
     
  END 
   LOOP;

 

 


例 6.

 

DECLARE 
  
     
  int 
    
  NUMBER 
  ( 
  2 
  ) : 
  = 
  0 
  ;
 
  BEGIN 
  
   LOOP
       
  int 
   : 
  = 
    
  int 
    
  + 
    
  1 
  ;
      DBMS_OUTPUT.PUT_LINE( 
  ' 
  int 的当前值为: 
  ' 
  || 
  int 
  );
       
  EXIT 
    
  WHEN 
    
  int 
    
  = 
  10 
  ;
    
  END 
   LOOP;
 
  END 
  ;

 

2.  WHILE 循环


WHILE 
    
  < 
  布尔表达式 
  > 
   LOOP
    要执行的语句;
 
  END 
   LOOP;


 

 



 

例7.


DECLARE 
   
  x  
  NUMBER 
   : 
  = 
  1 
  ;
 
  BEGIN 
  
    
  WHILE 
   x 
  <= 
  10 
   LOOP
      DBMS_OUTPUT.PUT_LINE( 
  ' 
  X的当前值为: 
  ' 
  || 
  x);
       x: 
  = 
   x 
  + 
  1 
  ;
    
  END 
   LOOP;
 
  END 
  ;

 

3.  数字式循环


 


[ 
  <<循环标签>> 
  ] 
  
 
  FOR 
   循环计数器  
  IN 
    
  [ 
   REVERSE  
  ] 
   下限 .. 上限 LOOP
  要执行的语句;
 
  END 
   LOOP  
  [ 
  循环标签 
  ] 
  ;

 

每循环一次,循环变量自动加1;使用关键字REVERSE,循环变量自动减1。跟在IN REVERSE 后面的数字必须是从小到大的顺序,而且必须是整数,不能是变量或表达式。可以使用EXIT 退出循环。


例8.


BEGIN 
  
    
  FOR 
    
  int 
     
  in 
    
  1 
  .. 
  10 
   LOOP
       DBMS_OUTPUT.PUT_LINE( 
  ' 
  int 的当前值为:  
  ' 
  || 
  int 
  );
    
  END 
   LOOP;
 
  END 
  ;

 

例 9.

 

CREATE 
    
  TABLE 
   temp_table(num_col  
  NUMBER 
  );

 
  DECLARE 
  
    V_counter  
  NUMBER 
   : 
  = 
    
  10 
  ;
 
  BEGIN 
  
    
  INSERT 
    
  INTO 
   temp_table(num_col)  
  VALUES 
   (v_counter );
    
  FOR 
   v_counter  
  IN 
    
  20 
   ..  
  25 
   LOOP
       
  INSERT 
    
  INTO 
   temp_table (num_col )  
  VALUES 
   ( v_counter );
    
  END 
   LOOP;
    
  INSERT 
    
  INTO 
   temp_table(num_col)  
  VALUES 
   (v_counter );
    
  FOR 
   v_counter  
  IN 
    
  REVERSE 
    
  20 
   ..  
  25 
   LOOP
       
  INSERT 
    
  INTO 
   temp_table (num_col )  
  VALUES 
   ( v_counter );
    
  END 
   LOOP;
 
  END 
   ;

 
  DROP 
    
  TABLE 
   temp_table;

 

例10:

 

DECLARE 
  
   TYPE jobids_varray  
  IS 
   VARRAY( 
  12 
  )  
  OF 
    
  VARCHAR2 
  ( 
  10 
  );  
  -- 
  定义一个VARRAY数据类型 
  
 
     v_jobids JOBIDS_VARRAY;  
  -- 
  声明一个具有JOBIDS_VARRAY数据类型的变量 
  
 
     v_howmany  
  NUMBER 
  ;  
  -- 
  声明一个变量来保存雇员的数量 
  
 
  
 
  BEGIN 
  
    
  -- 
  用某些job_id值初始化数组 
  
 
     v_jobids : 
  = 
   jobids_varray( 
  ' 
  FI_ACCOUNT 
  ' 
  ,  
  ' 
  FI_MGR 
  ' 
  ,  
  ' 
  ST_CLERK 
  ' 
  ,  
  ' 
  ST_MAN 
  ' 
  );

    
  -- 
  用FOR...LOOP...END LOOP循环使用每个数组成员的值 
  
 
      
  FOR 
   i  
  IN 
   v_jobids.FIRST..v_jobids.LAST LOOP

    
  -- 
  针对数组中的每个岗位,决定该岗位的雇员的数量 
  
 
         
  SELECT 
    
  count 
  ( 
  * 
  )  
  INTO 
   v_howmany  
  FROM 
   employees  
  WHERE 
   job_id  
  = 
   v_jobids(i);
      DBMS_OUTPUT.PUT_LINE (  
  ' 
  岗位 
  ' 
  || 
  v_jobids(i) 
  || 
  
                        
  ' 
  总共有 
  ' 
  || 
   TO_CHAR(v_howmany)  
  || 
    
  ' 
  个雇员 
  ' 
  );
    
  END 
   LOOP;
 
  END 
  ;

 

例11 在While循环中嵌套loop循环

/* 
   求100至110之间的素数 
   */ 
   
 
   DECLARE 
   
   v_m  
   NUMBER 
    : 
   = 
     
   101 
   ;
   v_i  
   NUMBER 
   ;
   v_n  
   NUMBER 
    : 
   = 
     
   0 
   ;
 
   BEGIN 
   
    
   WHILE 
    v_m  
   < 
     
   110 
    LOOP
      v_i : 
   = 
     
   2 
   ;
      LOOP
          
   IF 
    mod(v_m, v_i)  
   = 
     
   0 
     
   THEN 
   
            v_i : 
   = 
     
   0 
   ;
             
   EXIT 
   ;
          
   END 
     
   IF 
   ;
    
         v_i : 
   = 
    v_i  
   + 
     
   1 
   ;
          
   EXIT 
     
   WHEN 
    v_i  
   > 
    v_m  
   - 
     
   1 
   ; 
       
   END 
    LOOP;
      
       
   IF 
    v_i  
   > 
     
   0 
     
   THEN 
   
         v_n : 
   = 
    v_n  
   + 
     
   1 
   ;
         DBMS_OUTPUT.PUT_LINE( 
   ' 
   第 
   ' 
   || 
    v_n  
   || 
     
   ' 
   个素数是 
   ' 
     
   || 
    v_m);
       
   END 
     
   IF 
   ;

      v_m : 
   = 
    v_m  
   + 
     
   2 
   ;
    
   END 
    LOOP;
 
   END 
   ;

3.4GOTO

PL/SQL中GOTO语句是无条件跳转到指定的标号去的意思。语法如下:

GOTO 
   label;
......
 
  << 
  label 
  >> 
    
  /* 
  标号是用<< >>括起来的标识符  
  */

 

注意,在以下地方使用是不合法的,编译时会出错误。

u 跳转到非执行语句前面。

u 跳转到子块中。

u 跳转到循环语句中。

u 跳转到条件语句中。

u 从异常处理部分跳转到执行。

u 从条件语句的一部分跳转到另一部分。


例12:

DECLARE 
  
   V_counter  
  NUMBER 
   : 
  = 
    
  1 
  ;
 
  BEGIN 
  
   LOOP 
     DBMS_OUTPUT.PUT_LINE( 
  ' 
  V_counter的当前值为: 
  ' 
  || 
  V_counter);
     V_counter : 
  = 
   v_counter  
  + 
    
  1 
  ;
    
  IF 
   v_counter  
  > 
    
  10 
    
  THEN 
  
        
  GOTO 
   labelOffLOOP;
    
  END 
    
  IF 
  ;
    
  END 
   LOOP;
    
  << 
  labelOffLOOP 
  >> 
  
     DBMS_OUTPUT.PUT_LINE( 
  ' 
  V_counter的当前值为: 
  ' 
  || 
  V_counter);
 
  END 
  ;

 

例13:

DECLARE 
   
   v_i  
   NUMBER 
    : 
   = 
     
   0 
   ;
   v_s  
   NUMBER 
    : 
   = 
     
   0 
   ;
 
   BEGIN 
   
    
   << 
   label_1 
   >> 
   
   v_i : 
   = 
    v_i  
   + 
     
   1 
   ;
    
   IF 
    v_i  
   <= 
     
   1000 
     
   THEN 
   
      v_s : 
   = 
    v_s  
   + 
    v_i;
       
   GOTO 
    label_1;
    
   END 
     
   IF 
   ;
   DBMS_OUTPUT.PUT_LINE(v_s);
 
   END 
   ;

3.5语句

在PL/SQL 程序中,NULL语句是一个可执行语句,可以用 null 语句来说明“不用做任何事情”的意思,相当于一个占位符或不执行任何操作的空语句,可以使某些语句变得有意义,提高程序的可读性,保证其他语句结构的完整性和正确性。如:

例14:

 

DECLARE 
  
    ...
 
  BEGIN 
  
    ...
     
  IF 
   v_num  
  IS 
    
  NULL 
    
  THEN 
  
     
  GOTO 
   labelPrint;
     
  END 
    
  IF 
  ;
  …
   
  << 
  labelPrint 
  >> 
  
   
  NULL 
  ;  
  -- 
  不需要处理任何数据。 
  
 
  END 
  ;

 

 

例15:

 

DECLARE 
  
   v_emp_id employees.employee_id 
  % 
  TYPE;
   v_first_name employees.first_name 
  % 
  TYPE;
   v_salary employees.salary 
  % 
  TYPE;
   v_sal_raise  
  NUMBER 
  ( 
  3 
  , 
  2 
  );
 
  BEGIN 
  
   v_emp_id : 
  = 
    
  & 
  emp_id;
    
  SELECT 
   first_name, salary  
  INTO 
   v_first_name, v_salary
    
  FROM 
   employees  
  WHERE 
   employee_id  
  = 
   v_emp_id;
    
  IF 
   v_salary  
  <= 
    
  3000 
    
  THEN 
  
      v_sal_raise : 
  = 
   . 
  10 
  ;
      DBMS_OUTPUT.PUT_LINE(v_first_name 
  || 
  ' 
  的工资是 
  ' 
  || 
  v_salary
                                        
  || 
  ' 
  、工资涨幅是 
  ' 
  || 
  v_sal_raise);
    
  ELSE 
  
       
  NULL 
  ;
    
  END 
    
  IF 
  ;
 
  END 
  ;



作者:EricHu(DB、C/S、B/S、WebService、WCF、PM等)