Oracle系列之三——开发包

包(Package),顾名思义,用于逻辑组合相关的pl/sql类型。同java一样,我们可以将处理同一业务逻辑的相关代码或全局变量放在一个包中。通过使用pl/sql包,不仅能简化应用设计,提高应用性能,而且还可以实现信息隐藏、子程序重载等功能。我们应该学会以下内容:

①建立包规范和包体

②在包内定义公用组件和私有组件

③使用重载特征

④建立构造过程

⑤使用纯度级别

建立包

包由包规范(package specification)和包体(Package body)两部分组成。当建立包时,应先建立包规范,然后再建立包体。

  1. 建立包规范

    包规范实际上是包与应用程序之间的接口,它用于定义包的公用组件,包括常量、变量、游标、过程和函数等。在包规范中所定义的公用组件不仅可以在包内引用,而且也可以由其它的子程序引用。

    建立包规范时,需要注意,为了实现信息的隐藏,不应该将所有组件全部放在包规范处定义,而应该只定义公用组件。

    语法如下:

    Create [or replace ] package package_name

    Is | as

    Public type and item declarations

    Subprogram specifications

    End package_name;

     

如:

create or replace package dept_package as

v_deptno dept.deptno%type:=30;

procedure add_dept(deptno dept.deptno%type,

dname dept.dname%type,

loc dept.loc%type);

function get_dept(deptno dept.deptno%type) return varchar2;

end dept_package;

  1. 建立包体

    包体用于实现在包规范中所定义的过程和函数。当建立包体中,还可以在其中建立私有组件(实现信息隐藏),包括变量、常量、过程和函数等,但是所定义的私有组件只能在包内使用,而不能由其它子程序引用。

    语法如下:

    Create or replace package body package_name

    Is | as

    Private type and item declarations

    Subprogram bodies

    End package_name;

     

    我们在这里实现上面创建的包规范。

create or replace package body dept_package as

function validate_deptno(v_deptno dept.deptno%type) return boolean is

v_name varchar2(10);

begin

select dname into v_name from dept where deptno = v_deptno;

return true;

exception

when no_data_found then

return false;

end;

--参数名字必须和包规范中声明的完全一样,数据类型一样oracle无法解析为同一个函数。

procedure ADD_DEPT(v_deptno dept.deptno%type,

v_dname dept.dname%type,

v_loc dept.loc%type) is

begin

if validate_deptno(v_deptno) then

dbms_output.put_line('雇员已存在');

else

insert into dept values(v_deptno, v_dname, v_loc);

end if;

end;

--参数名字必须和包规范中声明的完全一样,数据类型一样oracle无法解析为同一个函数。

function GET_DEPT(v_deptno dept.deptno%type) return varchar2 is

v_name varchar2(10);

begin

if validate_deptno(v_deptno) then

select dname into v_name from dept where deptno = v_deptno;

return v_name;

else

raise_application_error(-20000,'部门号不存在');

end if;

end;

end dept_package;

 

注意:包规范语句和包体语句一定要分两次执行,不然会报错。也就是包规范创建完成,才能创建包体。

  1. 调用包

    如果在同一包中,则直接写函数名即可;如果在包在调用,则package_name.function_name();如果用其它成员调用,则为username_package_name_function_name();

    如果调用远程数据库中的包则为:package_name.function_name@db_link();

4.删除包

如果只是删除包体,可以用drop package body package_name;

如果同时删除包规范和包体,则为drop package package_name;

二,使用包重载

重载(overload是指多个具有相同名称的子程序。定义包时,使用重载特性,可以使用户在调用相同名称的组件时可以使用不同参数传递数据。比如,当查询员工工资时,可能希望输入员工工号,也可能是员工姓名,此时就需要使用包的重载特性。

举例如下:

包规范:

create or replace package body sal_package as

function get_sal(v_empno emp.empno%type) return number;

function get_sal(v_name emp.ename%type) return number;

end sal_package;

 

 

包体如下:

create or replace package body sal_package as

function get_sal(v_empno emp.empno%type) return number is

v_sal emp.sal%type;

begin

select sal into v_sal from emp where empno = v_empno;

return v_sal;

exception

when no_data_found then

dbms_output.put_line('该雇员号不存在');

return null;

end;

function get_sal(v_name emp.ename%type) return number is

v_sal emp.sal%type;

begin

select sal into v_sal from emp where ename = v_name;

return v_sal;

exception

when no_data_found then

dbms_output.put_line('该雇员名不存在');

return null;

end;

end sal_package;

三.使用包构造过程

在包中定义了全局变量以后,有些情况下,会话中可能还需要初始化全局变量,此时可以使用包的构造函数,类似于高级语言中的构造函数。当在会话第一次调用包的公用组件时,会自动执行其构造函数,并且该构造过程在同一会话内只会执行一次。

下面来说明使用包构造过程的方法:

在包规范中,没有有关包构造过程的任何信息,如下:

create or replace package sal_update_package as

minsal number(6,2);

maxsal number(6,2);

procedure update_sal(v_eno emp.empno%type, v_sal emp.sal%type);

end sal_update_package;

 

包体。包的构造过程没有任何名称,它只是在其它过程实现完成之后,以

Begin开始、以end结束的部分,如下:

create or replace package body sal_update_package as

procedure update_sal(v_eno emp.empno%type, v_sal emp.sal%type) is

begin

if v_sal between minsal and maxsal then

update emp set emp.sal = v_sal where emp.empno = v_eno;

if sql%notfound then

raise_application_error(-20003,'该雇员不存在');

end if;

else

raise_application_error(-20003,'工资不在范围内');

end if;

end;

begin

select max(sal), min(sal) into maxsal, minsal from emp;

end;

--一定要注意,这里没有end sal_update_package;

 

当在同一会话中第一次调用包的公用组件进,会自动执行其构造过程,而将来再调用其它组件时不会再调用其构造过程,所以构造过程是"只调用一次"的过程。

四.使用纯度级别

当使用包的公用函数时,它可以作为表达式的一部分,也可以作为SQL语句中使用.但如果在sql语句中引用包的公用函数,那么该公用函数不能包含DML语句(insert,update,delete),也不能读写远程包的变量。为了对包的公用函数加以限制,在定义包规范时可以使用纯度级别(Purity level)限制包的公有函数。定义纯度级别的语句如下:

Pragma restrict_references (function_name,wnds[,wnps][,rnds][,rnps]);

Pragma:表示这是一个编译指令,在编译的时候执行。

WNDS用于限制函数不能修改数据库数据,即不允许DML操作;WNPS用于限制不能修改包变量,即不能给包变量赋值;RNDS用于限制公用函数不能读取数据库数据,即不能用SELECT操作;RNPS用于限制不能读取包变量,即不能变包变量赋值给其它变量。

下面已不能修改包变量为例。

建立包规范:

create or replace package purity_demo as

maxsal number(6,2);

minsal number(6,2);

function get_maxsal return number;

function get_minsal return number;

pragma restrict_references(get_maxsal, wnps);

pragma restrict_references(get_minsal, wnps);

end purity_demo;

 

建立包体:

create or replace package body purity_demo as

 

function get_maxsal return number is

begin

select max(sal) into maxsal from emp;

return maxsal;

end;

function get_minsal return number is

begin

select min(sal) into minsal from emp;

end;

 

endpurity_demo;

 

在包体中函数修改了包变量的值,那么当在编译时,就会报错:

虽然不能修改,但可能读取。下面我们将包体改成如下形式:

create or replace package body purity_demo as

function get_maxsal return number is

begin

return maxsal;

end;

function get_minsal return number is

begin

return minsal;

end;

begin

select max(sal), min(sal) into maxsal, minsal from emp;

end;

 

 

 

本文档是在学习《Oracle.10g.PL_SQL编程》一书时的记录文档。若喜欢,请购买正版书籍。

 

参考文档:

《Oracle.10g.PL_SQL编程》:王海亮 林立新 于三禄 郑建茹 等编著,第十二章。

转载于:https://www.cnblogs.com/xiaozhi123/p/3644743.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值