Oracle中包(Package)
⼀、什么要使⽤包?
在⼀个⼤型项⽬中,可能有很多模块,⽽每个模块⼜有⾃⼰的过程、函数等。⽽这些过程、函数默认是放在⼀起的(如在PL/SQL中,过程默认都是放在⼀起的,即Procedures中),这些⾮常不⽅便查询和维护,甚⾄会发⽣误删除的事件。
PL/SQL为了满⾜程序模块化的需要,引⼊了包的构造。通过使⽤包就可以分类管理过程和函数等。
(1)包是⼀种数据库对象,相当于⼀个容器。将逻辑上相关的过程、函数、变量、常量和游标组合成⼀个更⼤的单位。⽤户可以从其他 PL/SQL 块中对其进⾏引⽤
(2)包类似于C++和JAVA语⾔中的类,其中变量相当于类中的成员变量,过程和函数相当于类⽅法。把相关的模块归类成为包,可使开发⼈员利⽤⾯向对象的⽅法进⾏开发,具有⾯向对象程序设计语⾔的特点,
(4)PL/SQL的包具有信息隐蔽性(information hiding),仅在算法和数据结构设计有关层可见。可将过程说明和过程体组成⼀个程序单位。也可将过程说明与它的过程体分开。也可在包中定义过程,⽽该过程在包说明中没有定义过程说明,这样定义的过程仅在包内使⽤。
(5)在PL/SQL程序设计中,使⽤包不仅可以使程序设计模块化,对外隐藏包内所使⽤的信息(通过使⽤私⽤变量),⽽写可以提⾼程序的执⾏效率。因为,当程序⾸次调⽤包内函数或过程时,ORACLE将整个包调⼊内存,当再次访问包内元素时,ORACLE直接从内存中读取,⽽不需要进⾏磁盘I/O操作,从⽽使程序执⾏效率得到提⾼。
⼆、包结构
⼀个包由两个分开的部分组成:包规范和包体
2.1包定义(PACKAGE)
(1)包定义(PACKAGE):包定义部分是为应⽤程序的接⼝,声明包内数据类型、变量、常量、游标、⼦程序和异常错误处理等元素,这些元素为包的公有元素。
CREATE [OR REPLACE] PACKAGE package_name
{IS | AS}
[公有数据类型定义]
[公有游标声明]
[公有变量、常量声明]
[公有⼦程序声明]
END [package_name];
2.2包主体(PACKAGE BODY)
包主体(PACKAGE BODY):包主体则是包定义部分的具体实现,它定义了包定义部分所声明的游标和⼦程序,在包主体中还可以声明包的私有元素。如果在包主体中的游标或⼦程序并没有在包头中定义,那么这个游标或⼦程序是私有的。
CREATE [OR REPLACE] PACKAGE BODY package_name
{IS | AS}
[私有数据类型定义]
[私有变量、常量声明]
[私有⼦程序声明和定义]
[公有⼦程序定义]
BEGIN
执⾏部分(初始化部分)
END [package_name];
与类相同,包中的程序元素也分为公⽤元素和私⽤元素两种,这两种元素的区别是他们允许访问的程序范围不同,即它们的作⽤域不同。公⽤元素不仅可以被包中的函数、过程所调⽤,也可以被包外的PL/SQL程序访问,⽽私有元素只能被包内的函数和过程序所访问。
包定义和包主体分开编译,并作为两部分分开的对象存放在数据库字典中。包定义⼀定要在包主体前⾯编译,包主体可以没有,但包定义⼀定要有)包的名称和包体的名称要保持⼀致
三、包举例
定义包规范
CREATE OR REPLACE
package p_stu
as
--定义结构体
type re_stu is record(
rname student.name%type,
rage student.age%type
);
--定义游标
type c_stu is ref cursor;
--定义函数
function numAdd(num1 number,num2 number)return number;
-
-定义过程
procedure GetStuList(cid in varchar2,c_st out c_stu);
end;
说明 type c_stu is ref cursor;
type c_stu:定义类型变量
is ref cursor:相当于数据类型,不过是引⽤游标的数据类型。
这种变量通常⽤于存储过程和函数返回结果集时使⽤,因为PL/SQL不允许存储过程或函数直接返回结果集,但可以变量,于是引⽤游标的类型变量作为输出参数或返回值就应运⽽⽣了。
定义包体:
CREATE OR REPLACE
package body p_stu
as
--游标和结构体,包规范中已声明,包体中不⽤再声明,直接使⽤。
--实现⽅法
function numAdd(num1 number,num2 number)return number
as
num number;
begin
num:=num1+num2;
return num;
end;
--实现过程
procedure GetStuList(cid varchar2,c_st out c_stu)
as
r_stu re_stu; --直接使⽤包规范中的结构
begin
open c_st for select name,age from student where classid=cid;
-- 如果已经在过程中遍历了游标,在使⽤这个过程的块中,将没有值。
-- loop
-- fetch c_st into r_stu;
-- exit when c_st%notfound;
-- dbms_output.put_line('姓名='||ame);
-- end loop;
end;
end;oracle游标的使用
调⽤包
declare
c_stu p_stu.c_stu; --定义包中游标变量
r_stu _stu; --定义包中结构体变量
num number;
begin
--使⽤及遍历包中过程返回的结果集
p_stu.GetStuList('5',c_stu);
loop
fetch c_stu into r_stu;
exit when c_stu%notfound;
dbms_output.put_line('姓名='||ame);
end loop;
--使⽤包中的⽅法
select p_stu.numAdd(5,6) into num from dual;
dbms_output.put_line('Num='||num);
end;
参考
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论