要查 invalid 对象,先用 select owner, object_name, object_type, status from all_objects where status = 'invalid' and object_type in ('procedure', 'function', 'package', 'package body', 'trigger', 'view'); 确认范围;再按类型用 alter … compile 手动编译;批量可用 sql*plus 脚本或 utl_recomp.recomp_parallel;编译后务必 show errors 并检查残留;注意 package 与 package body 状态可能不一致,ora-04068 需重启会话或刷新共享池。

查哪些对象是 INVALID 的,先看清楚范围
别急着编译,先确认当前用户或指定 schema 下到底有哪些无效对象。直接查 ALL_OBJECTS 最稳妥,它自动过滤掉你没权限看到的对象:
SELECT owner, object_name, object_type, status FROM ALL_OBJECTS WHERE status = 'INVALID' AND object_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE', 'PACKAGE BODY', 'TRIGGER', 'VIEW');- 如果用的是 DBA 权限,可改查
DBA_OBJECTS,但注意加owner条件,避免误操作其他 schema - 特别留意
PACKAGE BODY和PACKAGE是两个独立对象,状态可能不一致 —— 一个 VALID、一个 INVALID 很常见
用 ALTER … COMPILE 手动编译单个对象
这是最可控的方式,适合定位问题或验证修复效果。注意不同对象类型语法差异很大:
-
存储过程:
ALTER PROCEDURE scott.proc1 COMPILE; - 函数:
ALTER FUNCTION scott.func1 COMPILE; - 包头(spec):
ALTER PACKAGE scott.pkg1 COMPILE PACKAGE; - 包体(body):
ALTER PACKAGE scott.pkg1 COMPILE BODY; - 视图/触发器:
ALTER VIEW scott.vw1 COMPILE;或ALTER TRIGGER scott.trg1 COMPILE; - 编译后务必执行
SHOW ERRORS—— 即使返回 “Compilation succeeded.”,也可能只是语法通过,逻辑错误仍存在
批量编译:SQL*Plus 脚本生成 + 执行
适合一次性清理大量对象,且不想写 PL/SQL。关键点是把 PACKAGE BODY 单独处理,否则会报 ORA-04043:
- 生成脚本:
spool recompile_all.sql SELECT 'ALTER ' || object_type || ' ' || owner || '.' || object_name || CASE WHEN object_type = 'PACKAGE BODY' THEN ' COMPILE BODY;' WHEN object_type IN ('PROCEDURE','FUNCTION','PACKAGE','TRIGGER','VIEW') THEN ' COMPILE;' ELSE ';' END FROM ALL_OBJECTS WHERE status = 'INVALID' AND object_type IN ('PROCEDURE','FUNCTION','PACKAGE','PACKAGE BODY','TRIGGER','VIEW'); spool off - 执行:
@recompile_all.sql - 别漏掉
SET FEEDBACK OFF和SET VERIFY OFF,否则输出里全是干扰信息
调用 UTL_RECOMP.RECOMP_PARALLEL 并行编译(Oracle 10g+)
这是 Oracle 官方推荐的批量修复方式,尤其适合大库或紧急恢复场景,但有隐藏约束:
- 必须以
SYS或SYSDBA身份执行,普通用户会报 ORA-01031 - 执行前确保
job_queue_processes > 0,否则并行线程数为 0,实际变成串行 - 常用命令:
EXEC UTL_RECOMP.RECOMP_PARALLEL(4, 'SCOTT');—— 指定 4 线程编译 SCOTT 下所有无效对象 - 它不会报错中断,但失败对象仍留在
DBA_OBJECTS中 status = INVALID;建议执行完立刻查一遍残留:SELECT * FROM DBA_OBJECTS WHERE status = 'INVALID' AND owner = 'SCOTT'; - 不要在 DDL 高频期运行,UTL_RECOMP 会锁依赖链上的对象,容易和业务 DDL 冲突死锁
真正麻烦的不是编译失败,而是编译成功后调用时报 ORA-04068 —— 这说明包变量状态被清空了,而会话还缓存着旧上下文。这种情况下,必须让应用重启连接,或显式执行 ALTER SYSTEM FLUSH SHARED_POOL;(慎用,影响全局)。











