包用于将oracle相关的嵌套表、record、varray、记录、游标以及子程序逻辑组合在一起的一种方法。它由包规范(package specification)和包体(package body)两部分组成,其中保规范实际是包与其他应用程序之间的接口,它用于定义包的公用组件,包括常量、变量、游标、过程和函数等;包体中定义的组件只能在包内使用。
在user_source数据字典视图中可以查询得到包的定义和实现代码。
包的重载属性类似与高级语言中的相同定义,主要是为了实现功能相同,而传入参数不同的调用过程。
create
or
replace
package
pack_tsalary
is
P_departid tsalary.departid%
type
;
--
重载过程,根据传入参数更新对应记录的
salary
procedure
upd_salary(aemployeeid
number
);
procedure
upd_salary(adepartid
varchar2
);
end
;
在包中定义了全局变量之后,有些情况下,会话中可能还需要初始化全局变量,此时可以使用包的构造过程,该过程没有任何名称,它位于程序尾部,并以begin end包括起来。在会话内第一次调用包的公用组件时,会自动执行其构造过程。
--select * from tsalary;
create
or
replace
package
body
pack_tsalary
is
procedure
upd_salary(aemployeeid
number
)
is
myexception
exception
;
begin
update
tsalary
set
salary =
100
where
employeeid = aemployeeid;
if
sql
%
notfound
then
raise
myexception;
end
if
;
exception
when
myexception
then
raise_application_error(-
20001
,
'
没发现员工
id
为
'
||aemployeeid||
'
的员工
'
);
end
;
procedure
upd_salary(adepartid
varchar2
)
is
begin
update
tsalary
set
salary =
1001
where
departid = adepartid;
if
sql
%
notfound
then
raise_application_error(-
20001
,
'
没发现部门
id
为
'
||adepartid||
'
的员工
'
);
end
if
;
end
;
--
构造函数,初始化全局变量
begin
p_departid :=
'departid'
;
end
;
包的公用函数既可以作为表达式的一部分使用,也可以在sql语句中使用。但如果要在sql语句中引用包的公用函数,那么该公用函数不能包含dml语句(insert/update/delete)也不能读写远程包的变量。例如有如下包定义:
create
or
replace
package
pack_tsalary
is
function
del_salary(aemployeeid
varchar2
)
return
number
;
end
;
create
or
replace
package
body
pack_tsalary
is
function
del_salary(aemployeeid
varchar2
)
return
number
is
begin
delete
from
tsalary
where
employeeid = aemployeeid;
return
1
;
end
;
那么基于表达式的调用方式可以成功:
if
sys
.pack_tsalary.del_salary(
'a'
) =
1
then
dbms_output.put_line(
'
删除信息成功
'
);
end
if
;
而将包函数放在
sql
语句调用时则会提示
ora-14551:
无法执行查询中的
dml
语句。
select
sys
.pack_tsalary.del_salary(
'1'
)
into
aboolean
from
dual;
dbms_output.put_line(aboolean);
为了避免这种调用错误的出现,我们可以使用
oracle
提供的纯度级别限制函数,对包的公用函数在定义时加以限制,定义纯度级别的语法为
pragma restrict_references(function_name,wnds[,wnps][,rnds][,rnps]);
其中
function_name
用于指定已经定义的函数名;
wnds
(
no write database
)用于限制函数不能修改数据库数据(也就是禁止执行
dml
操作);
wnps
(
no write package
)用于限制函数不能修改包变量;
rnds
(
no read database
)用于限制函数不能读取数据库数据;
rnps
(
no read package
)用于限制函数不能读取包变量。
create
or
replace
package
pack_tsalary
is
function
del_salary(aemployeeid
varchar2
)
return
number
;
pragma
restrict_references
(del_salary,
wnds
);
end
;
这时如果在包体对应函数中出现
dml
语句,则编译时就出错,错误提示为“
PLS-00452:
子程序
’del_salary’
违反了它的相关编译指示”
create
or
replace
package
body
pack_tsalary
is
function
del_salary(aemployeeid
varchar2
)
return
number
is
begin
delete
from
tsalary
where
employeeid = aemployeeid;
return
1
;
end
;
end
;