Oracle的包(Package)

这篇文章上次修改于 5 个月前,可能部分内容已经不适用,如有疑问可询问作者。

Oracle的包(Package)

以下是Oracle包的案例说明,结合了PL/SQL的实际应用场景:

示例:员工管理包(EMPLOYEE_MGMT)

SQL
-- 包规范(声明接口)
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;
Copy

包的核心特点:

  1. 模块化组织
    将员工管理相关的程序单元(存储过程、函数)和数据结构(类型、游标)封装在单个逻辑单元中,提升代码复用性。

  2. 接口与实现分离
  3. 规范部分声明公共元素(类似接口)
  4. 主体部分包含具体实现细节 (支持独立编译和版本管理)

  5. 状态持久性
    包级变量和游标在会话期间保持状态,适用于需要跨多次调用的场景(如分页查询)

典型应用场景:

SQL
-- 调用包中的存储过程
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;
Copy

包的优势总结:

  • 通过封装实现信息隐藏(私有过程/函数不暴露给外部)
  • 减少数据库对象间的依赖关系
  • 支持重载(同名不同参数的子程序)
  • 提升整体性能(包首次调用时整体加载到内存)

实际开发中常见包类型:
1. 数据校验包(包含各种校验规则)
2. 报表生成包(封装复杂业务逻辑)
3. 系统工具包(通用日志记录、异常处理)