[推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆)

简介:

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

控制语句: IF 语句

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

顺序语句: 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  循环

 1.  简单循环

 

  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.4  标号和GOTO 

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

 

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

 

 

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

跳转到非执行语句前面。

跳转到子块中。

跳转到循环语句中。

跳转到条件语句中。

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

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

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  NULL 语句 

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 ;

 


本文转自yonghu86 51CTO博客,原文链接:http://blog.51cto.com/yonghu/1321352,如需转载请自行联系原作者

相关文章
|
24天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL游标自定义异常:数据探险家的“专属警示灯”
【4月更文挑战第19天】Oracle PL/SQL中的游标自定义异常是处理数据异常的有效工具,犹如数据探险家的警示灯。通过声明异常名(如`LOW_SALARY_EXCEPTION`)并在满足特定条件(如薪资低于阈值)时使用`RAISE`抛出异常,能灵活应对复杂业务规则。示例代码展示了如何在游标操作中定义和捕获自定义异常,提升代码可读性和维护性,确保在面对数据挑战时能及时响应。掌握自定义异常,让数据管理更从容。
|
24天前
|
SQL Oracle 安全
Oracle的PL/SQL游标异常处理:从“惊涛骇浪”到“风平浪静”
【4月更文挑战第19天】Oracle PL/SQL游标异常处理确保了在数据操作中遇到的问题得以优雅解决,如`NO_DATA_FOUND`或`TOO_MANY_ROWS`等异常。通过使用`EXCEPTION`块捕获并处理这些异常,开发者可以防止程序因游标问题而崩溃。例如,当查询无结果时,可以显示定制的错误信息而不是让程序终止。掌握游标异常处理是成为娴熟的Oracle数据管理员的关键,能保证在复杂的数据环境中稳健运行。
|
24天前
|
SQL Oracle 安全
Oracle的PL/SQL异常处理方法:守护数据之旅的“魔法盾”
【4月更文挑战第19天】Oracle PL/SQL的异常处理机制是保障数据安全的关键。通过预定义异常(如`NO_DATA_FOUND`)和自定义异常,开发者能优雅地管理错误。异常在子程序中抛出后会向上传播,直到被捕获,提供了一种集中处理错误的方式。理解和善用异常处理,如同手持“魔法盾”,确保程序在面对如除数为零、违反约束等挑战时,能有效保护数据的完整性和程序的稳定性。
|
24天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL中FOR语句循环游标的奇幻之旅
【4月更文挑战第19天】在Oracle PL/SQL中,FOR语句与游标结合,提供了一种简化数据遍历的高效方法。传统游标处理涉及多个步骤,而FOR循环游标自动处理细节,使代码更简洁、易读。通过示例展示了如何使用FOR循环游标遍历员工表并打印姓名和薪资,对比传统方式,FOR语句不仅简化代码,还因内部优化提升了执行效率。推荐开发者利用这一功能提高工作效率。
|
24天前
|
SQL Oracle 关系型数据库
Oracle的PL/SQL游标属性:数据的“导航仪”与“仪表盘”
【4月更文挑战第19天】Oracle PL/SQL游标属性如同车辆的导航仪和仪表盘,提供丰富信息和控制。 `%FOUND`和`%NOTFOUND`指示数据读取状态,`%ROWCOUNT`记录处理行数,`%ISOPEN`显示游标状态。还有`%BULK_ROWCOUNT`和`%BULK_EXCEPTIONS`增强处理灵活性。通过实例展示了如何在数据处理中利用这些属性监控和控制流程,提高效率和准确性。掌握游标属性是提升数据处理能力的关键。
|
3天前
|
SQL 存储 数据库连接
LabVIEW与SQL Server 2919 Express通讯
LabVIEW与SQL Server 2919 Express通讯
|
4天前
|
SQL Windows
安装SQL Server 2005时出现对性能监视器计数器注册表值执行系统配置检查失败的解决办法...
安装SQL Server 2005时出现对性能监视器计数器注册表值执行系统配置检查失败的解决办法...
13 4
|
5天前
|
SQL 数据可视化 Oracle
这篇文章教会你:从 SQL Server 移植到 DM(上)
这篇文章教会你:从 SQL Server 移植到 DM(上)
|
5天前
|
SQL 关系型数据库 数据库
SQL Server语法基础:入门到精通
SQL Server语法基础:入门到精通
SQL Server语法基础:入门到精通
|
5天前
|
SQL 存储 网络协议
SQL Server详细使用教程
SQL Server详细使用教程
27 2