包是Oracle数据库中一种重要的PL/SQL程序结构,它将逻辑相关的变量、常量、游标、异常、过程和函数组织在一起,提供了更好的封装性和模块化。在大型项目中,可能有很多模块,而每一个模块又有自己的存过、函数等。而这些存过、函数默认是放在一起的,如果所有的存过函数都是放在一起的那么非常不容易查询和维护,甚至会发生误删除事件。
目录
一、包的组成
1. 包规范(Package Specification)包头、包定义
2. 包体(Package Body)
二、包的优势
三、创建包
1. 包规范语法
2. 包体语法
四、包示例
1. 完整包示例
包规范(emp_pkg.sql):
包体(emp_pkg_body.sql):
2、完整简单示例
五、包的使用
1. 调用包中的子程序
2. 使用包常量
3. 处理包异常
六、包的重载
七、包的初始化
八、包的持久状态
九、系统内置包
十、最佳实践
一、包的组成
1. 包规范(Package Specification)包头、包定义
-
定义包的公共接口
-
声明可供外部访问的对象
-
不包含具体实现代码
包定义部分声明包内数据类型、变量、常量、游标、子程序和异常错误处理元素,这些元素是包的公有元素。
2. 包体(Package Body)
-
实现包规范中声明的子程序
-
可以包含私有对象(仅在包内可见)
-
实现包初始化代码
包主体则是包定义部分的具体实现,它定义了包定义部分所声明的游标和子程序,在包主体中还可以声明包的私有元素。
包定义和包主体要分开编译,并作为两部分分开的对象存放在数据字典中(user_source/all_source/dba_source),声明的时候包头和包体的变量类型一致,先执行包头,在执行包体。
二、包的优势
-
模块化:将相关功能组织在一起
-
封装性:隐藏实现细节,暴露清晰接口
-
性能提升:首次调用时整个包被加载到内存
-
减少依赖:修改包体不会使依赖对象失效
-
全局共享:包变量在会话期间保持状态
三、创建包
1. 包规范语法
CREATE [OR REPLACE] PACKAGE package_name
[IS|AS]-- 公共类型和常量声明-- 公共变量声明-- 公共异常声明-- 公共游标声明-- 过程和函数声明
END [package_name];-- 简单举例
create or replace package pak_name as|is
function fun_1(v1 in|out|in out 类型) return 类型;
function fun_2(v2 in|out|in out 类型) return 类型;
……
procedure pro_1(v3 in|out|in out 类型);
procedure pro_2(v4 in|out|in out 类型);
……
end pack_name;
2. 包体语法
CREATE [OR REPLACE] PACKAGE BODY package_name
[IS|AS]-- 私有类型和常量声明-- 私有变量声明-- 私有异常声明-- 私有游标声明-- 过程和函数实现[BEGIN -- 初始化代码]
END [package_name];-- 简单举例
create or replace package body pak_name as|is
function fun_1(v1 in|out|in out 类型) return 类型as|isbegin 要执行的语句;returnend;
function fun_2(v2 in|out|in out 类型) return 类型as|isbegin 要执行的语句;returnend;
……
procedure pro_1(v3 in|out|in out 类型)as|isbegin 要执行的语句;end;
procedure pro_2(v4 in|out|in out 类型)as|isbegin 要执行的语句;end;
……
end pak_name;
四、包示例
1. 完整包示例
包规范(emp_pkg.sql):
CREATE OR REPLACE PACKAGE emp_pkg IS-- 公共常量c_min_salary CONSTANT NUMBER := 5000;-- 公共异常e_invalid_dept EXCEPTION;-- 公共游标CURSOR emp_by_dept_cursor(p_dept_id NUMBER) RETURN employees%ROWTYPE;-- 函数声明FUNCTION get_emp_count(p_dept_id NUMBER) RETURN NUMBER;-- 过程声明PROCEDURE update_salary(p_emp_id IN NUMBER,p_percent IN NUMBER DEFAULT 5,p_rows_updated OUT NUMBER);PROCEDURE hire_employee(p_first_name IN VARCHAR2,p_last_name IN VARCHAR2,p_email IN VARCHAR2,p_job_id IN VARCHAR2 DEF