PL/SQL语言仿效了ADA程序设计语言,因此在ADA语言中很多程序结构都适用于PL/SQL语言,而ADA语言仿效了Pascal程序语言,因此PL/SQL的基本特性与Pascal相似,比如赋值、比较运算符及单引号字符串等。
2.2.1PL/SQL块结构
块(Block)是进行PL/SQL程序开发时最基本的单位,所有的PL/SQL程序都是由块组成的,块又可以分为如下两类:
匿名块:没有名称的PL/SQL块,可以内嵌到应用程序中或者在Toad或SQL*PLUS中直接运行块。这种块通常由客户端程序产生,用来调用服务器上的子程序,这种块不会保存到数据库中。
命名块:具有名称的PL/SQL块,又可细分为3个部分,这种类型的块一般保存在服务器端的数据库中以备调用。
PL/SQL命名快分为以下3部分:
(1)使用<<块名称>>进行标识的块,通常是在块嵌套时,为了区分多级嵌套层次关系而使用命名加以区分。
(2)由函数或过程组成的子程序块,这种块保存在数据库中。
(3)数据库触发器块,触发器块是指当数据库中某个事件触发后要执行的PL/SQL语句块。
1.PL/SQL块的组成
无论是命名块还是匿名块都是由3个部分组成,如下所示:
(1)定义部分:定义常量、变量、游标、异常及复杂数据类型等。
(2)执行部分:包含了要执行的PL/SQL语句和SQL语句,用于实现应用模块的功能。
(3)异常处理部分:用于捕捉执行部分可能出现的运行错误,并编写出错后的代码。
一个PL/SQL的基本机构如下所示:
DECLARE --可选
--定义部分
BEGIN --必须
--执行部分
EXCEPTION --可选
--异常处理部分
END;
定义部分从DECLARE开始,这是可选的,一个PL/SQL块可以有定义区也可以没有,同样EXCEPTION也是可选的,一个最小的PL/SQL语句块必须至少具有一个BEGIN-END 以及一条可执行的命令。一个最简单的PL/SQL块如下代码所示。
--最简单的PL/SQL块
BEGIN
dbms_output.put_line('最简单的PL/SQL块');
END;
这段代码仅向屏幕上打印了一行信息,如果省略了dbms_output,PL/SQL将提示编译失败,错误提示如下图所示。
如果需要编写什么都不做的PL/SQL块,可以简单的在BEGIN和EDN之间放一个NULL,如下面代码所示。
BEGIN
NULL;
END;
NULL语句是一个可执行语句,表示的意思是“什么都不做”,相当于一个不执行任何操作的占位符。NULL语句通常用来使某些语句有意义,提高程序的可读性。
2.匿名PL/SQL块实例
以下展示一个完整的包含定义部分、执行部分及异常处理部分的匿名PL/SQL语句块,这个实例将向class_msg(年级信息)表中插入信息,首先在stu_msg表中查询该年级学生数量之后将数量更新到class_msg中。
declare
--学生数量
v_stuNum number(5);
--定义年级变量为1
v_className varchar2(20) := '1';
--年级数量
v_classNum number(5);
begin
--查询该年级的学生数量
select count(1) into v_stuNum from stu_msg where stu_class = v_className;
--查询是否有该年级的信息记录
select count(1)
into v_classNum
from class_msg
where class_name = v_className;
--没有就插入
if v_classNum = 0 then
insert into class_msg
(class_name, stu_num)
values
(v_className, v_stuNum);
--否则更新
else
update class_msg set stu_num = v_stuNum where class_name = v_className;
end if;
--异常处理块
exception
--如果出现异常
when others then
--弹出异常信息
dbms_output.put_line('年级信息插入或更新失败');
end;
代码实现步骤如下:
(1)在DECLARE中定义了变量,一个用用来记录学生数量,一个保存了默认值为’1’的年级,一个用来记录年级信息的数量。
(2)查询默认值年级的学生数量,查询该年级信息在class_msg中是否存在,不存在则INSERT操作向数据库中插入一条数据,否则UPDATE操作更新该条记录的学生数量。
(3)如果在操作过程中出现任何异常,将执行EXCEPTION部分的代码,在屏幕有上输出操作失败的信息。
3.使用嵌套块
在PL/SQL中可以嵌套子块,嵌套的块既可以放在外部块的执行部分,也可以放在异常处理部分,但是不能放在外部块的声明部分。使用嵌套块可以使得程序代码可读性更强。
注意:额你不嵌套块可以访问外部块中定义的变量,但是外部块不能访问嵌套块中定义的变量。
通过嵌套快对之前的代码进行加强,实现如下所示:
--使用嵌套块插入或更新班级学生数量
declare
--学生数量
v_stuNum number(5);
--定义年级变量为1
v_className varchar2(20) := '1';
--目前概年级存储的学生的数量
v_stuNumNow number(5);
begin
--内部嵌套块
--查询该年级的学生数量
begin
select count(1)
into v_stuNum
from stu_msg
where stu_class = v_className;
select stu_num
into v_stuNumNow
from class_msg
where class_name = v_className;
end;
--内部嵌套块
--执行更新操作
begin
update class_msg set stu_num = v_stuNum where class_name = v_className;
dbms_output.put_line('执行更新操作成功');
end;
--异常处理块
exception
--如果出现异常
when NO_DATA_FOUND then
--在异常处理快内部嵌套块
begin
insert into class_msg
(class_name, stu_num)
values
(v_className, v_stuNum);
dbms_output.put_line('执行插入操作成功');
end;
end;
可以看到代码由四个块组成,一个外部块内嵌了三个嵌套块,嵌套块如下图示意。
(1)第一个块,茶查询该年级学生的数量,查询年级信息表中存储的该年级的学生数量,如果SELECT-INTO没有检索到数据,就会触发 NO_DATA_FOUND异常,因此程序的执行逻辑会跳转到异常处理部分。
(2)第二个嵌套块在第一个成功执行后执行。 这个块用来更新年级信息表。
(3)第三个嵌套块定义在异常部分,这个块首先插入一行年级数据,如果插入数据的过程中出现异常