Oracle PL/SQL 包依赖管理详解

Oracle PL/SQL 包依赖管理详解

适用版本:Oracle Database 10g / 11g / 12c / 19c / 23ai 文档版本:v1.0 / 2026-07


1. 概述

PL/SQL 包依赖管理保证代码稳定性[1]:

详细见:Oracle PL/SQL 包设计与最佳实践


2. 依赖类型

2.1 直接

- A 调用 B
- A 依赖 B

2.2 间接

- A 调用 B,B 调用 C
- A 间接依赖 C

2.3 本地

- 同 Schema
- 远程(DB Link)

3. 查看

3.1 依赖

SELECT name, type, referenced_name, referenced_type
FROM user_dependencies
WHERE name = 'EMP_PKG';

-- 反向
SELECT name, type
FROM user_dependencies
WHERE referenced_name = 'EMPLOYEES';

3.2 编译错误

SELECT object_name, object_type, status
FROM user_objects
WHERE status = 'INVALID';

-- 详细
SELECT name, type, line, position, text
FROM user_errors;

3.3 对象

SELECT object_name, object_type, status, last_ddl_time
FROM user_objects
WHERE object_type IN ('PACKAGE', 'PACKAGE BODY', 'PROCEDURE', 'FUNCTION')
ORDER BY object_name;

4. 失效原因

4.1 依赖对象变更

- 表结构变更
- 视图重定义
- 类型变更
- 包重编译

4.2 权限

- 权限撤销
- 角色变更

4.3 远程

- DB Link 失效
- 远程对象变更

5. 重新编译

5.1 手动

ALTER PACKAGE emp_pkg COMPILE;
ALTER PACKAGE emp_pkg COMPILE SPECIFICATION;
ALTER PACKAGE emp_pkg COMPILE BODY;

ALTER PROCEDURE my_proc COMPILE;
ALTER FUNCTION my_func COMPILE;
ALTER TRIGGER my_trig COMPILE;
ALTER VIEW my_view COMPILE;

5.2 批量

-- Schema
@?/rdbms/admin/utlrp.sql

-- 或
EXEC UTL_RECOMP.RECOMP_SERIAL('SCOTT');
EXEC UTL_RECOMP.RECOMP_PARALLEL(4, 'SCOTT');

5.3 自动

ALTER SYSTEM SET plsql_optimize_level = 2;
-- 自动重编译

6. 编译参数

6.1 PLSQL_CCFLAGS

ALTER SESSION SET PLSQL_CCFLAGS = 'DEBUG:TRUE,VERSION:2';

6.2 PLSQL_OPTIMIZE_LEVEL

ALTER SESSION SET PLSQL_OPTIMIZE_LEVEL = 2;  -- 0-3

6.3 PLSQL_CODE_TYPE

ALTER SESSION SET PLSQL_CODE_TYPE = NATIVE;  -- INTERPRETED / NATIVE

6.4 PLSQL_WARNINGS

ALTER SESSION SET PLSQL_WARNINGS = 'ENABLE:ALL';

7. 条件编译

7.1 基本

CREATE OR REPLACE PROCEDURE my_proc IS
BEGIN
  $IF $$DEBUG $THEN
    DBMS_OUTPUT.PUT_LINE('Debug mode');
  $END
  
  $IF $$VERSION > 1 $THEN
    -- 新版本代码
  $ELSE
    -- 旧版本代码
  $END
END;
/

7.2 设置

ALTER SESSION SET PLSQL_CCFLAGS = 'DEBUG:TRUE,VERSION:2';

7.3 查看

SELECT name, value 
FROM user_plsql_object_settings 
WHERE name = 'MY_PROC';

8. 循环依赖

8.1 问题

- A 依赖 B
- B 依赖 A
- 无法编译

8.2 解决

- 重构
- 提取公共到 C
- 接口
- 动态调用

8.3 动态调用

-- A 调用 B(动态)
EXECUTE IMMEDIATE 'BEGIN b_pkg.proc(:1); END;' USING p_arg;
-- 避免静态依赖

9. 版本管理

9.1 编译时间

SELECT object_name, object_type, created, last_ddl_time, status
FROM user_objects
WHERE object_type = 'PACKAGE BODY'
ORDER BY last_ddl_time DESC;

9.2 源代码

SELECT name, type, line, text
FROM user_source
WHERE name = 'EMP_PKG'
ORDER BY line;

9.3 版本控制

- 脚本文件
- Git
- Flyway / Liquibase

详细见:Oracle SQL 开发规范详解


10. 重编译脚本

10.1 自动

BEGIN
  FOR rec IN (
    SELECT object_name, object_type
    FROM user_objects
    WHERE status = 'INVALID'
      AND object_type IN ('PACKAGE', 'PACKAGE BODY', 'PROCEDURE', 'FUNCTION', 'TRIGGER', 'VIEW')
  ) LOOP
    BEGIN
      EXECUTE IMMEDIATE 'ALTER ' || rec.object_type || ' ' || rec.object_name || ' COMPILE';
      DBMS_OUTPUT.PUT_LINE('Compiled: ' || rec.object_name);
    EXCEPTION
      WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('Failed: ' || rec.object_name || ' - ' || SQLERRM);
    END;
  END LOOP;
END;
/

10.2 依赖顺序

-- 按依赖顺序
-- 1. 类型
-- 2. 表
-- 3. 序列
-- 4. 视图
-- 5. 包规范
-- 6. 包主体
-- 7. 过程/函数
-- 8. 触发器

11. 监控

11.1 失效对象

SELECT object_name, object_type, status
FROM user_objects
WHERE status = 'INVALID'
ORDER BY object_type, object_name;

11.2 警告

SELECT name, type, sequence, line, position, text
FROM user_errors
ORDER BY name, sequence;

11.3 编译时间

SELECT object_name, object_type, last_ddl_time
FROM user_objects
WHERE last_ddl_time > SYSDATE - 1
ORDER BY last_ddl_time DESC;

12. 应用场景

12.1 部署

- 脚本顺序
- 依赖管理
- 编译

12.2 变更

- 表结构变更
- 重编译依赖
- 测试

12.3 升级

- 版本
- 兼容
- 迁移

13. 常见坑与排错

13.1 失效

- 依赖变更
- 自动重编译
- 手动

13.2 编译错误

- 语法
- 类型
- 权限

13.3 循环

- 重构
- 动态调用

14. 最佳实践

  1. 依赖顺序:编译
  2. utlrp.sql:批量
  3. 监控失效:及时
  4. 条件编译:版本
  5. 避免循环:重构
  6. 动态调用:解耦
  7. 版本控制:管理
  8. 测试:验证
  9. 文档:依赖
  10. 自动化:脚本

15. 参考资料

[1] Oracle Database PL/SQL Language Reference 19c, “Dependencies” https://docs.oracle.com/en/database/oracle/oracle-database/19/lnpls/plsql-packages.html