在PL/SQL程序开发中,为了方便实现模块化程序的管理,可以将PL/SQL元素(如存储过程、函数、变量、常量、自定义数据类型、游标等)根据模块的程序结构组织在一起,存放在一个包中,称为一个完整的单元,并在编译之后存储在数据库服务器中,作为一种全局结构,供应用程序调用。
在Oracle数据库中,包有两类,一类是系统内置的包,每个包实现特定的应用过程、函数、常量等的集合,如DBMS_OUTPUT.put_line()就是调用了DBMS_OUTPUT包中的put_line()函数;
另一类是根据应用需要由用户创建的包。
包由包规范(specification)和包体(body)两部分组成,在数据库中独立存储。包的创建包括包规范和包体的创建。
2.包的创建和应用
- 包的创建
创建包规范的格式如下:
CREATE [OR REPLACE] PACKAGE 包名称IS|AS
元素名称定义(类型、变量、存储过程、函数、游标、异常等)
END [包名称];
元素声明的顺序可以是任意的,但必须先声明再使用。过程和函数只声明,不进行具体的实现。
包体负责包规范中定义的函数或存储过程的具体代码实现,如果在包体中定义了包规范中没有的元素,则此部分元素将被设置为私有访问,只能由同一包中的函数或存储过程使用。此外只有在包规范已经创建的条件下,才可以创建包体,如果包规范中不包含任何函数或存储过程,则可以不创建包体。
创建包体的格式如下:
CREATE [OR REPLACE] PACKAGE BODY 包名称IS|AS
元素结构实现;
END [包名称];
在创建包体时需要注意:
包体中的名称应与包规范中的包名称保持一致。
包体中存储过程和函数的声明格式必须与包规范中的声明完全一致。
包的调用格式如下:
begin
pkg_demo.proc_insert_users(‘2022-1-5’,‘yyyy-mm-dd’);
pkg_demo.proc_update_users(‘2022-10-5’,‘yyyy-mm-dd’);
end;
【例7-15】创建一个包,该包中包括一个存储过程PRINT_ENAME,在包体中使用存储过程实现输出文字的功能,然后在建立存储过程调用该包。
具体代码如下:
—创建包规范
create or replace package EMPLOYEE_PKG
as
procedure PRINT_ENAME;
end EMPLOYEE_PKG;
—创建包体
CREATE OR REPLACE PACKAGE BODY employee_pkg as
Procedure print_ename is
Begin
Dbms_output.put_line(‘我们一定要学习好数据库’);
End print_ename;
End employee_pkg;
—创建调用该包
CREATE OR REPLACE Procedure callEMPLOYEEPKG
as
begin
EMPLOYEE_PKG.PRINT_ENAME;
End callEMPLOYEEPKG;
执行后,如图7-23所示。
图7-23执行计算职工年薪函数
2)包的持续性
在包规范中,所有声明的元素都具有全局作用域,元素的值在整个用户会话期间将一直存在,因此在用户会话期间,元素可以在应用程序各个部分的代码中被引用。每个用户会话都会维护属于自己会话的元素的副本,用户之间的元素互不干扰。这种在用户会话期间元素值和状态的持续性被称为包的持续性。包的持续性具体可以体现在包中变量的持续性和游标持续性上。
变量的持续性是指,当用户调用包时,系统会为每个调用者创建属于该用户的变量副本,并在用户的整个会话期间持续存在。包变量对当前会话用户是私有的。
【例7-16】在test用户下创建一个包,该包中包括变量 pkgvar,设置该变量初始值为0。建立存储过程proc_set_var重新给该变量赋值,然后在建立函数fun_get_var 调用包pkgvar。
登录scott用户,在该用户下调用存储过程proc_set_var给变量赋值为10,查询变量 pkgvar
的值。登录sy 用户,在该用户下调用存储过程proc_set_var给变量赋值为20,在scott下查询变量 pkgvar的值。
本例中两个不同用户同时对一个包变量进行存取操作,通过变量值验证包变量在用户会话期间的持续性。
创建包含变量的包,存储过程代码如下:
create or replace package pkg_varas
pkgvar number:=0;
end pkg_var;
–创建设置变量值的存储过程
create or replace procedure proc_set_var(p_var number)as
begin
pkg_var.pkgvar:=p_var;
end proc_set_var;
创建获取包变量值的函数,代码如下:
create or replace function fun_get_var return number
As
begin
return pkg_var.pkgvar;
end fun_get_var;
登录scott 用户,调用存储过程后,查询函数中变量的值,代码如下:
Connect scott/tiger@ ;
EXECUTE proc_set_var(10);
Select fun_ get_var FROM dual ;
执行后,如图7-24所示。
图7-24查看变量的值
由上述结果可以看出,此时包变量的值为10。接下来通过用户 sys启动另一个 SQL * Plus 窗口,此时访问testt用户下包变量的值仍为初始值0,然后重新设置包变量值为20,代码如下:
登录到sys用户,查看变量的值
Connect sys/sjk@orcl;
–给变量赋值为20
EXECUTE proc_set_var(20);
Select fun_get_var from dual;
接下来回到scott用户下,此时再次查询包变量的值,会发现包变量仍为10,并没有受 用户操作的影响,
3)使用数据字典,查看包
通过查询数据字典视图user_objects、user_source查看当前用户的所有包规范、包体,具体代码如下:
select object_type,object_name,status from user_objectswhere object_type in (‘PACKAGE’,‘PACKAGE BODY’);
执行后如图7-25所示。
图7-25查看包的基本信息
4)重新编译包
包的重新编译包括对包规范和包体整体进行重新编译或者分别进行重新编译。其语法如下:
alter package 包名称 compile;
alter package 包名称 compile specification;
alter package 包名称 compile body;
COMPILE表示重新编译包规范和包体。
COMPILE SPECIFICATION 表示重新编译包规范。
COMPILE BODY表示重新编译包体。
分别重新编译包规范和包体
alter package pkg_varas compile specification;
alter package pkg_varas compile body;
5)删除包
当不需要使用定义的包规范或包时,用户可以使用删除整个包,也可以只删除包体。
删除包格式如下:
drop package 包的名称;
删除包规范的同时会将其对应的包体一起删除。
6)系统常用包
在Oracle中,除了可以使用用户创建的包外,还可以利用Oracle系统所提供的开发部进行代码的编写,方便应用程序的开发。下述是几个常用的系统包:
dbms_output包:是最常用的一个系统包 。
dbms_output.put_line()函数就是其中的一个子程序。
dbms_alter包:用于数据库报警,允许会话间通信。
dbms_job包:用于任务调度服务。
dbms_lob包:用于处理大对象操作。
dbms_pipe包:用于数据库管道,允许会话间通信。
dbms_sql包:用于执行动态SQL。
utl_file包:用于文件的输入输出。
除了utl_file包存储在服务器和客户端外,其他的包均存储在服务器中。