包的基本概念 包是一种程序模块化设计的实现手段。通过包将一个模块所需要的程序(过程,函数,游标,类型)结构统一管理,同时包与包之间也可以互相调用; 定义包需要两个组成部分: 包规范(PACKAGE):定义包中可以被外部访问的部分,在包规范中声明的内容可以从应用程序和包的任何地方访问,语法:
CREATE OR [REPLACE] PACKAGE 包名称 [AUTHID CURRENT_USER | DEFINER] IS | AS 结构名称定于(类型,过程,函数,游标,异常等) END [包名称]; /
[AUTHID CURRENT_USER | DEFINER]为权限设置,
如果包规范中的某个操作可以由使用者权限决定,则将其设置为CURRENT_USER, 在包规范中所定义的所有子程序权限必须与包规范声明时定义的权限相同
包体(PACKAGE BODY):负责包规范中定于的函数或过程的具体实现代码,如果在包体中定义了包规范中没有的内容,则此部分内容将被设置为私有访问,包体的定义语法如下:CREATE OR [REPLACE] PACKAGE BODY 包名称 IS |AS 结构实现(类型,过程,函数,游标,异常等) BEGIN 包初始化程序代码; END [包名称]; /
示例1:定义包规范CREATE OR REPLACE PACKAGE mldn_pkg
AS
FUNCTION get_emp_fun(p_dno dept.deptno%TYPE) RETURN SYS_REFCURSOR ; --返回弱游标类型
END ;
/
分析: 定义了一个包规范,此规范定义了一个get_emp_fun()函数,该函数可被任何应用程序调用,该函数的返回值类型为SYS_REFCURSOR
方法2:自己定义弱类型游标
CREATE OR REPLACE PACKAGE mldn_pkg
AS
TYPE cursor_ref IS REF CURSOR ;
FUNCTION get_emp_fun(p_dno dept.deptno%TYPE) RETURN cursor_ref ;
END ;
/
示例2:定义包体实现get_emp_fun()函数
CREATE OR REPLACE PACKAGE BODY mldn_pkg
AS
FUNCTION get_emp_fun(p_dno dept.deptno%TYPE) RETURN SYS_REFCURSOR
AS
cur_var SYS_REFCURSOR ;
BEGIN
OPEN cur_var FOR SELECT * FROM emp WHERE deptno=p_dno ; --打开参数游标
RETURN cur_var ;
END ;
END ;
/
方法2:自定义游标变量
CREATE OR REPLACE PACKAGE BODY mldn_pkg
AS
FUNCTION get_emp_fun(p_dno dept.deptno%TYPE) RETURN cursor_ref
AS
cur_var cursor_ref ;
BEGIN
OPEN cur_var FOR SELECT * FROM emp WHERE deptno=p_dno ; --打开参数游标
RETURN cur_var ;
END ;
END ;
/
通过user_objects与user_source查询包的信息 示例1:查询user_objects数据字典确认包规范及包体信息SELECT object_type , object_name , status FROM user_objects
WHERE object_type IN ('PACKAGE','PACKAGE BODY') ;
示例2:查询user_source数据字典,查看包规范SELECT *
FROM user_source
WHERE type='PACKAGE' AND name='MLDN_PKG' ;
包的调用 示例1:定义PL/SQL程序块调用包中的函数DECLARE
v_receive SYS_REFCURSOR ;
v_empRow emp%ROWTYPE ; --定义行类型
BEGIN
v_receive := mldn_pkg.get_emp_fun(10) ;
LOOP
FETCH v_receive INTO v_empRow ; --取得游标数据
EXIT WHEN v_receive%NOTFOUND ; --如果没有数据则退出
DBMS_OUTPUT.put_line('雇员姓名:' || v_empRow.ename || ',雇员职位:' || v_empRow.job) ;
END LOOP ;
END ;
/
示例2:如果不使用SYS_REFCURSOR,则在声明v_receive变量时,就需要通过包定义类型
DECLARE
v_receive mldn_pkg.cursor_ref ;
v_empRow emp%ROWTYPE ; --定义行类型
BEGIN
v_receive := mldn_pkg.get_emp_fun(10) ;
LOOP
FETCH v_receive INTO v_empRow ; --取得游标数据
EXIT WHEN v_receive%NOTFOUND ; --如果没有数据则退出
DBMS_OUTPUT.put_line('雇员姓名:' || v_empRow.ename || ',雇员职位:' || v_empRow.job) ;
END LOOP ;
END ;
/
删除包 删除包规范语法:
DROP PACKAGE 包名称;
删除包体DROP PACKAGE BODY 包名称;
示例1:删除mldn_pkg包DROP PACKAGE mldn_pkg ;
此时删除的是包规范,删除的同时包体会一并删除
重新编译包 语法:ALTER PACKAGE 包名称 COMPILE [DEBUG] PACKAGE | SPECIFICATION | BODY [REUSE SETTINGS];
包的重新编译有3种编译形式:PACKAGE
重新编译包规范和包体
SPECIFICATION
重新编译包规范
BODY
重新编译包体
示例1:重新编译包规范ALTER PACKAGE mldn_pkg COMPILE SPECIFICATION ;
示例2:重新编译包体ALTER PACKAGE mldn_pkg COMPILE BODY ;