Package包
包是用来管理逻辑相关,数量较多的pl/sql过程和函数,一般declare 声明的所有内容都可以包含在包内
包是采用单组命令创建的相关函数,过程和变量的集合
包简化应用设计,提高应用性能,实现信息隐藏,子程序重载等
一:建包语法
包的组成: 包说明 + 包体
包说明:可以认为是包的内容表,包含过程,函数定义等
包体:包含实现包说明的函数和过程的所有代码,同时还有函数/过程的说明(虽然该说明在包说明中有了)
CREATE PACKAGE 包名称
...
IS/AS
...
END;
CREATE PACKAGE BODY 名称
IS/AS
...
END;
1.1包的优点
1.模块化:包能把逻辑相关的类型,常量,变量,异常和子程序放到一个命令的pl/sql,每个包都容易理解
2.轻松的程序设计:无包体也可编写编译,在完成整个应用程序前,不需要完全实现包体部分
3.信息隐藏:有私有的子程序不可见,公有的子程序可见
4.附加功能:打包公有变量和游标在一个会话期会一直存在,所以,它们可以被当前环境下的所有子程序共享,并且他们允许跨事务来维护数据而不用把它保存在数据库中
5.良好的性能:首次调用包就被加载到内存中,以后调用包的子程序就不需要再读取磁盘.包能阻塞级联依赖,这样就避免不必要的编译.
二:创建包
创建包之前先建立包规范,然后再建包.
2.1包规范
包规范是包与应用程序的接口,用于定义包的公用组件,包括常量,变量,游标,过程和函数等.
注意:
1.为了实现信息隐藏,不应该将所有的组件放在包规范处定义,而应该只定义公有组件.
2.为了减少因为代码改变而引起的重编译,尽量不要在包规范部分放置过多的内容.
3.包规范改变需要重编译,但是包体内容改变不需要重编译
--定义一个公用变量my_id
--一个公用过程my_pro
--一个公用函数my_fun
CREATE OR REPLACE PACKAGE my_package
IS
my_id NUMBER := 1;
PROCEDURE my_pro(p_id IN NUMBER,p_name );
FUNCTION my_fun(f_id IN NUMBER) RETURN VARCHAR2;
END my_package;
注意:
1.公用的函数和过程只有在定义了包体后才可以调用
2.2包体
目的: 实现包规范的过程和函数
CREATE OR REPLACE PACKAGE BODY my_package IS --名字和包规范相同
FUNCTION validate_fun(v_id IN NUMBER) RETURN VARCHAR2 --私有函数
AS v_tmp t3.name%TYPE;
BEGIN
SELECT NAME INTO v_tmp FROM t3 WHERE ID=v_id;
RETURN v_tmp;
END validate_fun;
PROCEDURE my_pro(p_id IN NUMBER ) --公有过程
AS p_name t3.name%TYPE;
BEGIN
SELECT NAME INTO p_name FROM t3 WHERE ID=p_id;
END my_pro;
FUNCTION my_fun(f_id IN NUMBER) RETURN VARCHAR2 --公有函数
AS f_tmp t3.name%TYPE;
BEGIN
SELECT NAME INTO f_tmp FROM t3 WHERE ID=f_id;
RETURN f_tmp;
END my_fun;
END my_package_body;
注意:
1.私有组件在包体中定义,(变量/常量/过程/函数),而且私有组件只能在包内使用
2.包中的过程,函数可以与包外的函数,过程同名,但是具体实现不同
3.包体中同样重复会有包规范的函数和过程的声明
4.包体中定义的过程/函数,如果跟包规范中公有的函数/过程不同名称,就代表这个函数/过程是私有的
2.3调用包组件
格式: 包名.组件名称;
三:管理包
3.1查询已创建包
数据字典: USER_OBJECTS
select object_name,created,status from USER_OBJECTS where object_type=‘package’;
3.2查看包源码
数据字典: UESR_SOURCE
select text from USER_SOURCE where name=‘包名称’ and type = ‘package’;
3.3重编译
alter package 包名 compile;
3.4删除
drop package 包名;
四:系统内置包
4.1 DBMS_ALTER
DBMS_ALTER包能让数据库触发器在特定的数据库值发生变化时向应用程序发生警报.报警是基于事务且异步的.
使用包之前需要权限
SQL> GRANT EXECUTE ON DBMS_ALERT TO 用户名;
比如:
GRANT EXECUTE ON DBMS_ALERT TO scott;
实现报警功能开发步骤:
--1.创建触发器
CREATE OR REPLACE TRIGGER my_tri7 AFTER UPDATE OF ID ON t3 --触发器监控t3表的id,是否被update
BEGIN
DBMS_ALERT.SIGNAL('id_update_alert','t3表id被修改'); --使用dbms_alert包的signal指定报警消息 , id_update_alert是报警事件名称
END ;
--2.创建过程,用于注册触发器
CREATE OR REPLACE PROCEDURE my_pro2(NAME VARCHAR2)
AS
message VARCHAR2(20);
status INTEGER;
BEGIN
DBMS_ALERT.register(NAME); --注册报警事件,name代表事件名称 name=触发器的 id_update_alert
DBMS_ALERT.waitone(NAME,message,status); --等待报警事件发生 waitone/waitany都可以 , message实际=触发器的 't3表id被修改'
IF status = 0 THEN --status = 0说明事务已提交
dbms_output.put_line('请注意: '||message);
END IF;
DBMS_ALERT.remove(NAME); --移除报警事件
END;
--3.使用报警事件
SET serveroutput ON
BEGIN
FOR i IN 1..3 LOOP
my_pro2('id_update_alert'); --执行过程my_pro2,传入name参数,参数来自触发器
END LOOP;
END;
4.2 DBMS_JOB
用于安排和管理作业队列.
步骤:
1.使用DBMS_JOB包中的过程SUBMIT来创建作业
2.使用RUN来运行作业
4.3 DBMS_OUTPUT
用于打印信息
方式:
1.DBMS_OUTPUT.PUT_LINE();
2.SERVEROUTPUT ON
4.4 DBMS_PIPE
允许不同的会话通过命名管道来进行通信
步骤:
1.可以使用pack_message和send_message把消息封装到一个管道,然后把消息发送到同一个实例中的另一个会话中.
2.管道的另一个终端,可以使用过程receive_message和unpack_message来接受并打开要读取的消息.
4.5 DBMS_TRANSACTION
用于过程 , 函数和包中执行sql事务处理语句,其中提供了许多过程和函数
4.6 DBMS_SESSION
提供了使用pl/sql实现alter session命令,set role命令和其他会话信息的方法.
4.7 DBMS_ROWID
该包用于在pl/sql程序和sql语句中取得行标识符rowid的信息并创建rowid
4.8 DBMS_DDL
4.9 DBMS_RANDOM
该包提供了内置的随机数生成器
4.10 UTL_FILE
该包能让pl/sql程序读写操作系统os文本文件
4.11 UTL_HTTP
该包可以让pl/sql程序使用超文本传输协议http进行通信