本章内容
- 1.包概述
- 2.包的创建
- 3.包的调用
- 4.包重载
- 5.包的初始化
- 6.包的持续性
- 7.包的串行化
- 8.包的管理
包概述
1、包是包含一个或多个子程序单元(过程、函数等)的容器。
2、包是一种全局结构 。
3、包类型
- 数据库内置包
- 用户创建的包
4、包构成
- 包规范
- 包体两
1.包规范声明了软件包中所有内容,如过程、函数、游标、类型、异常和变量等,其中过程和函数只包括原型信息,不包含任何子程序代码。
2.包体中包含了在包头中的过程和函数的实现代码。包体中还可以包括在规范中没有声明的变量、游标、类型、异常、过程和函数,但是它们是私有元素,只能由同一包体中其他过程和函数使用。
包的创建
- 创建包规范
- 创建包体
(1)创建包规范
- 语法
create or replace package package_name is|as [pragma serially_resuable] type_definition|variable_declaration| exception_declaration|cursor_declaration| procedure_ declaration|function_ declaration end [package_name];
注意:
元素声明的顺序可以是任意的,但必须先声明后使用;
所有元素是可选的;
- 过程和函数的声明只包括原型,不包括具体实现。
- 创建一个软件包,包括2个变量、2个过程和1个异常。
(2)创建包体
- 语法
create or replace package body package_name is|as [pragma serially_resuable] type_definition|variable_declaration| exception_declaration| cursor_declaration| procedure_definition | function_definition end [package_name];
注意:
包体中函数和过程的原型必须与包规范中的声明完全一致;
只有在包规范已经创建的条件下,才可以创建包体;
如果包规范中不包含任何函数或过程,则可以不创建包体。
create or replace package body pkg_emp
as
procedure update_sal(p_empno number, p_sal number)
as
begin
select min(sal), max(sal) into minsal,maxsal from emp;
if p_sal between minsal and maxsal then
update emp set sal=p_sal where empno=p_empno;
if sql%notfound then
raise_application_error(-20000,'the employee doesn''t exist');
end if;
else
raise e_beyondbound;
end if;
exception
when e_beyondbound then
dbms_output.put_line('the salary is beyond bound! ');
end update_sal;
procedure add_employee(p_empno number,p_sal number)
as
begin
select min(sal), max(sal) into minsal,maxsal from emp;
if p_sal between minsal and maxsal then
insert into emp(empno,sal) values(p_empno,p_sal);
else
raise e_beyondbound;
end if;
exception
when e_beyondbound then
dbms_output.put_line('the salary is beyond bound! ');
end add_employee;
end pkg_emp;
包的调用
在包规范声明的任何元素是公有的,在包外都是可见的
包外:通过 package.element 形式调用;
包内:直接通过元素名进行调用。
- 在包体中定义而没有在包头中声明的元素是私有的,只能在包体中引用
- 调用软件包 pkg_emp 中的过程 update_sal ,修改 7844 员工工资为 3000 。调用 add_employee 添加一个员工号为 1357 ,工资为 4000 的员工。
begin pkg_emp.update_sal(7844,3000); pkg_emp.add_employee(1357,4000); end;
包重载
重载子程序必须同名不同参,即名称相同,参数不同。参数不同体现为参数的个数、顺序、类型等不同。
如果两个子程序参数只是名称和模式不同,则不能重载。
procedure overloadme (parameter1 in number); procedure overloadme (parameter2 out number);
不能根据两个函数返回类型不同而对它们进行重载。
function overloadme return date; function overloadme return number;
重载子程序参数必须在类型系列方面有所不同。
procedure overloadchar (parameter in char); procedure overloadchar (parameter in varchar2);
在一个包中重载两个过程,分别以部门号和部门名称为参数,查询相应部门员工名、员工号信息。
create or replace package pkg_overload as procedure show_emp(p_deptno number); procedure show_emp(p_dname varchar2); end pkg_overload;
create or replace package body pkg_overload
as
procedure show_emp(p_deptno number)
as
begin
for v_emp in (select * from emp where deptno=p_deptno) loop
dbms_output.put_line(v_emp.empno||' '|| v_emp.ename);
end loop;
end show_emp;
procedure show_emp(p_dname varchar2)
as
v_deptno number;
begin
select deptno into v_deptno from dept
where dname=p_dname;
for v_emp in (select * from emp
where deptno=v_deptno) loop
dbms_output.put_line(v_emp.empno||' '||
v_emp.ename);
end loop;
end show_emp;
end pkg_overload; 包的初始化
包在第一次被调用时从磁盘读取到共享池,并在整个会话的持续期间保持。在此过程中,可以自动执行一个初始化过程,对软件包进行实例化。
包的初始化过程只在包第一次被调用时执行,因此也称为一次性过程,它是一个匿名的 pl/sql 块,在包体结构的最后,以 begin 开始。
示例
在 pkg_emp 包中,在包初始化时给 minsal 和 maxsal 两个变量赋值,在子程序中直接引用这两个变量。
create or replace package pkg_emp
as
minsal number;
maxsal number;
e_beyondbound exception;
procedure update_sal(
p_empno number, p_sal number);
procedure add_employee(
p_empno number,p_sal number);
end pkg_emp;
create or replace package body pkg_emp
as
procedure update_sal(p_empno number, p_sal number)
as
begin
if p_sal between minsal and maxsal then
update emp set sal=p_sal where empno=p_empno;
if sql%notfound then
raise_application_error(-20000,'the employee
doesn''t exist');
end if;
else
raise e_beyondbound;
end if;
exception
when e_beyondbound then
dbms_output.put_line('the salary is beyond bound!');
end update_sal;
procedure add_employee(p_empno number,p_sal number)
as
begin
if p_sal between minsal and maxsal then
insert into emp(empno,sal) values(p_empno,p_sal);
else
raise e_beyondbound;
end if;
exception
when e_beyondbound then
dbms_output.put_line('the salary is beyond bound!');
end add_employee;
begin
select min(sal), max(sal) into minsal,maxsal from emp;
end pkg_emp;
包的持续性
- 变量持续性
- 游标持续性
(1)变量持续性
包中变量的持续性是指,当用户调用包时,会创建自己的变量副本,在用户的整个会话过程中持续存在,对用户而言是私有的。
为了测试变量的持续性,先创建一个包含一个变量的包和对包中变量进行读、写的两个过程。
create or replace package variable_pkg is pkg_test number(6,2) :=0; end variable_pkg; create or replace procedure get_pkg_test (p_test out number) is begin p_test := variable_pkg.pkg_test; end; create or replace procedure set_pkg_test (p_test in number) is begin variable_pkg.pkg_test := p_test; end;
以不同的用户(scott,system)分别启动两个sql*plus,进行下列操作,可以看出,包中的变量variable_pkg.pkg_test在scott用户和system用户之间是持续的、独立的。
--user scott sql>variable g_test number; sql>execute get_pkg_test(:g_test); sql>print g_test g_test ---------- 0 sql>execute set_pkg_test(10); sql>execute get_pkg_test(:g_test); sql>print g_test g_test ---------- 10
--user system sql>variable g_test number sql>execute scott.get_pkg_test(:g_test); sql>print g_test g_test ---------- 0 sql>execute scott.set_pkg_test(20); sql>execute scott.get_pkg_test(:g_test); sql>print g_test g_test ---------- 20
--user scott sql>execute get_pkg_test(:g_test); sql>print g_test g_test ---------- 10
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论