- 通过包可以实现多种程序结构的统一管理,包分为两个部分,即包规范,包体,只有在包规范中定义的程序结构才可以被其他程序所使用;
- 包中的子程序支持重载,只需要考虑参数以及个数的不同即可;
-
包中程序的纯度有4 种级别:WNDS,RNDS,WNPS,RNPS
-
包的基本概念
- 包是一种程序模块化设计的实现手段。通过包将一个模块所需要的程序(过程,函数,游标,类型)结构统一管理,同时包与包之间也可以互相调用;
-
定义包需要两个组成部分:
- 包规范(PACKAGE):定义包中可以被外部访问的部分,在包规范中声明的内容可以从应用程序和包的任何地方访问,语法:
CREATE OR [REPLACE] PACKAGE 包名称 | [AUTHID CURRENT_USER | DEFINER]为权限设置, 如果包规范中的某个操作可以由使用者权限决定,则将其设置为CURRENT_USER, |
- 包体(PACKAGE BODY):负责包规范中定于的函数或过程的具体实现代码,如果在包体中定义了包规范中没有的内容,则此部分内容将被设置为私有访问,包体的定义语法如下:
CREATE OR [REPLACE] PACKAGE BODY 包名称 |
- 示例1:定义包规范
CREATE OR REPLACE PACKAGE mldn_pkg AS FUNCTION get_emp_fun(p_dno dept.deptno%TYPE) RETURN SYS_REFCURSOR ; --返回弱游标类型 END ; / | 分析: | |
方法2:自己定义弱类型游标
|
|
- 示例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 ; |