PL/SQL之包的创建和使用处理

来源:互联网 发布:逆波兰算法 编辑:程序博客网 时间:2024/06/17 23:16

一,包的概念

包(PACKAGE)的全称叫程序包,是由一组相关的函数,过程,变量,游标等PL/SQL程序设计元素的组合。

包类似于java中的类,变量类似于类中的成员变量,函数和过程类似java类中的方法。

主要作用是把相同或相似的东西归类,方便维护和管理,提高开发效率,提高性能。

与高级语言中类是相同的,对于变量和函数等也分为公有元素和私有元素,元素的访问范围不同,即作用域不同。

公有元素其它程序包能够调用,私有元素只能在本包中调用。

包的封装前提是在你写的函数,过程等PL/SQL程序设计元素都完善的时候才进行封装的工作。

我们为什么要使用包?包的优点:

(1)简化应用程序设计

程序包的说明部分和包体部分可以分别创建各编译。主要体现  在以下三个方面:

可以在设计一个应用程序时,只创建各编译程序包的说明部分,然后再编写引用该程序包的 PL/SQL 块;

只要不改变包的说明部分,就可以单独调试、增加或替换包体的内容,这不会影响其他的应用程序。

更新包的说明后必须重新编译引用包的应用程序,但更新包体,则不需重新编译引用包的应用程序,以快
速进行进行应用程序的原形开发。

(2)模块化

可以将逻辑相同的PL/SQL块或者元素组合在一起,用名称标识唯一程序包。把一个大功能划分成各个小功能

模块,每个人负责开发一部分模块,最后在将各个元素组合在一起,逻辑清晰,开发效率高。

(3)信息隐藏

元素分为公有和私有两部分,公有大家都能访问,但私有元素只能本包访问,不用暴露包的细节,让使用者

拿到他应该拿到的,看不到他不应该或者不想让他看到的。

(4)效率高

程序包第一次被调用某个元素时,ORACLE将整个包加载到内存中,第二次访问时,直接从内存中读取,不需要

进行一系列I/O操作。

二,包的定义

包的定义由包说明定义和包主体定义两部分组成。

关于包体的说明:

包体只能在包说明被创建或编译后才能进行创建或编译。

在包体中实现的过程、函数、游标的名称必须与包说明中的过程、函数、游标一致,包括名称、参数的名
称以及参数的模式(IN、OUT、IN OUT)。

在包体中声明的数据类型、变量、常量都是私有的,只能在包体中使用而不能被印刷体外的应用程序访问
与使用。

在包体执行部分,可对包说明,包体中声明的公有或私有变量进行初始化或其它设置。

创建包的语法:

CREATE [OR REPLACE] PACKAGE package_name[AUTHID{CURRENT_USER|DEFINER}]--AUTHID CURRENT_USER 和 AUTHID DEFINER 选项说明应用程序在调用函数时所使用的权限模式IS|AS  [公有数据类型定义]  [公有游标声明]  [公有变量、常量声明]  [公有函数声明]  [公有过程声明]END [package_name];

创建包体的语法:

CREATE [OR REPLACE] PACKAGE BODY package_nameIS|AS  [私有数据类型定义]  [私有变量、常量声明]  [私有异常错误声明]  [私有函数声明和定义]  [私有函过程声明和定义]  [公有游标定义]  [公有函数定义]  [公有过程定义]BEGIN  --执行部分END package_name;
三,包的开发步骤

(1)包的元素函数,存储过程等调试完善

(2)定义包的声明

(3)定义包体

(4)调试包

四,包定义实例说明

建表,插入数据:

create table mytest(          id number(3) PRIMARY KEY,          name varchar2(20),          age number(3)        );        insert into mytest values(1,'one',18);        insert into mytest values(2,'two',20);        insert into mytest values(3,'three',24);        commit;  

创建包:

--创建包CREATE OR REPLACE PACKAGE pac_testIS  --变量定义  myvariable mytest%ROWTYPE;  --添加信息  FUNCTION add_mytest(v_id mytest.id%TYPE,v_name mytest.name%TYPE,v_age mytest.age%TYPE)  RETURN NUMBER;  --删除信息  FUNCTION delete_mytest(v_id mytest.id%TYPE)   RETURN NUMBER;  --查询数据  PROCEDURE query_mytest(v_id IN mytest.id%TYPE);END pac_test;

创建包体:

--创建包体CREATE OR REPLACE PACKAGE BODY pac_testIS  --添加信息  FUNCTION add_mytest(v_id mytest.id%TYPE,v_name mytest.name%TYPE,v_age mytest.age%TYPE)  RETURN NUMBER  IS    --自定义异常    myexc EXCEPTION;     PRAGMA EXCEPTION_INIT(myexc, -1); /* -1 是违反唯一约束条件的错误代码 */  BEGIN    INSERT INTO mytest VALUES(v_id,v_name,v_age);    IF SQL%FOUND THEN      RETURN 1;--插入成功    END IF;  EXCEPTION    WHEN myexc THEN      RETURN 0;--插入失败    WHEN OTHERS THEN      RETURN -1;  END add_mytest;  --删除信息  FUNCTION delete_mytest(v_id mytest.id%TYPE)   RETURN NUMBER  IS   BEGIN    DELETE FROM mytest WHERE id = v_id;    IF SQL%FOUND THEN      RETURN 1;--删除成功    ELSE       RETURN 0;--删除失败    END IF;  EXCEPTION    WHEN OTHERS THEN      RETURN -1;--删除异常  END delete_mytest;  --查询数据  PROCEDURE query_mytest(v_id IN mytest.id%TYPE)  IS  BEGIN    SELECT * INTO myvariable FROM mytest WHERE id = v_id;  EXCEPTION    WHEN NO_DATA_FOUND THEN      DBMS_OUTPUT.PUT_LINE('没有查到数据');    WHEN TOO_MANY_ROWS THEN      DBMS_OUTPUT.PUT_LINE('返回多行数据');    WHEN OTHERS THEN      DBMS_OUTPUT.PUT_LINE('抛异常了');  END query_mytest;BEGIN  NULL;END pac_test;
从工具中可以看到,创建完后包结构如图:

包调用:

DECLARE  v_num NUMBER;BEGIN  v_num:=PAC_TEST.add_mytest(4,'four',24);--包内容调用方式  commit;  DBMS_OUTPUT.PUT_LINE(v_num);  pac_test.query_mytest(1);  DBMS_OUTPUT.PUT_LINE(pac_test.myvariable.name);END;
五,子程序重载

PL/SQL 允许对包内子程序和本地子程序进行重载。所谓重载时指两个或多个子程序有相同的名称,但拥有
不同的参数变量、参数顺序或参数数据类型,同名不同参,跟java重载类似。

六,删除包

删除包的命令语法:

DROP PACKAGE [BODY] [user.]package_name;

七,包的管理

从上面截图可以清晰地看到包的结构,当包体发生改变时,需要从新编译包;

ALTER PACKAGE package_name COMPILE [PACKAGE|BODY|SPECIFICATION];

可以通过以下命令查看包的源码:

 select text from user_source where name = 'PAC_TEST';

可以看到包,包体源码。




0 0