五、Oracle 中的包(Package)

五、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操作,从而使程序执行效率得到提高。

包结构

一个包由两个分开的部分组成:包规范包体

包定义(package)

(1) 包定义(package):包定义部分是为应用程序的接口,声明包内数据类型、变量、常量、游标、子程序和异常错误处理等元素,这些元素为包的公有元素。

create or replace package package_name
[is | as]
  [公有数据类型定义]
  [公有游标声明]
  [公有变量、常量声明]
  [公有子程序声明]
end [package_name];

包主体

包主体(package body):包主体则是包定义部分的具体实现,它定义了包定义部分所声明的游标和子程序,在包主体中还可以声明包的私有元素。如果在包主体中的游标或子程序并没有在包头中定义,那么这个游标或子程序是私有的。

create or replace package package_name
[is | as]
  [公有数据类型定义]
  [公有游标声明]
  [公有变量、常量声明]
  [公有子程序声明]
   begin
      执行部分(初始化部分)
end [package_name];

与类相同,包中的程序元素也分为公用元素和私用元素两种,这两种元素的区别是他们允许访问的程序范围不同,即它们的作用域不同。公用元素不仅可以被包中的函数、过程所调用,也可以被包外的PL/SQL程序访问,而私有元素只能被包内的函数和过程序所访问。

包定义和包主体分开编译,并作为两部分分开的对象存放在数据库字典中。包定义一定要在包主体前面编译,包主体可以没有,但包定义一定要有。 包的名称和包体的名称要保持一致。

包举例

定义学生表并插入数据

create table student(
  classid varchar2(5),
  name varchar2(10),
  age number(5)
);
insert into student values('5', '李白', 23);
insert into student values('1', '杜甫', 32);

定义包规范

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 in 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('姓名='||r_stu.rname);
       -- end loop;
  end;
end;
/

调用包

set serveroutput on
declare
  c_stu p_stu.c_stu;   --定义包中游标变量
  r_stu p_stu.re_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('姓名='||r_stu.rname);
  end loop;
   
   --使用包中的方法
   select p_stu.numAdd(5,6) into num from dual;
  dbms_output.put_line('Num='||num);
end;
/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值