Oracle的包(Package)
以下是Oracle包的案例说明,结合了PL/SQL的实际应用场景:
示例:员工管理包(EMPLOYEE_MGMT)
-- 包规范(声明接口)
CREATE OR REPLACE PACKAGE employee_mgmt AS
PROCEDURE add_employee(
p_empno NUMBER,
p_ename VARCHAR2,
p_sal NUMBER
);
FUNCTION get_salary(
p_empno NUMBER
) RETURN NUMBER;
-- 声明记录类型
TYPE emp_rec IS RECORD (
empno emp.empno%TYPE,
ename emp.ename%TYPE,
sal emp.sal%TYPE
);
-- 声明游标
CURSOR emp_cursor RETURN emp_rec;
END employee_mgmt;
-- 包主体(实现逻辑)
CREATE OR REPLACE PACKAGE BODY employee_mgmt AS
PROCEDURE add_employee(
p_empno NUMBER,
p_ename VARCHAR2,
p_sal NUMBER
) IS
BEGIN
INSERT INTO emp(empno, ename, sal)
VALUES (p_empno, p_ename, p_sal);
COMMIT;
END add_employee;
FUNCTION get_salary(
p_empno NUMBER
) RETURN NUMBER IS
v_sal emp.sal%TYPE;
BEGIN
SELECT sal INTO v_sal
FROM emp
WHERE empno = p_empno;
RETURN v_sal;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN NULL;
END get_salary;
CURSOR emp_cursor RETURN emp_rec IS
SELECT empno, ename, sal
FROM emp
WHERE sal > 3000;
END employee_mgmt;
包的核心特点:
模块化组织
将员工管理相关的程序单元(存储过程、函数)和数据结构(类型、游标)封装在单个逻辑单元中,提升代码复用性。- 接口与实现分离
- 规范部分声明公共元素(类似接口)
主体部分包含具体实现细节 (支持独立编译和版本管理)
状态持久性
包级变量和游标在会话期间保持状态,适用于需要跨多次调用的场景(如分页查询)
典型应用场景:
-- 调用包中的存储过程
BEGIN
employee_mgmt.add_employee(7788, 'SCOTT', 4500);
END;
-- 调用包中的函数
DECLARE
v_salary NUMBER;
BEGIN
v_salary := employee_mgmt.get_salary(7788);
DBMS_OUTPUT.PUT_LINE('Salary: ' || v_salary);
END;
包的优势总结:
- 通过封装实现信息隐藏(私有过程/函数不暴露给外部)
- 减少数据库对象间的依赖关系
- 支持重载(同名不同参数的子程序)
- 提升整体性能(包首次调用时整体加载到内存)
实际开发中常见包类型:
1. 数据校验包(包含各种校验规则)
2. 报表生成包(封装复杂业务逻辑)
3. 系统工具包(通用日志记录、异常处理)