PLS-00123修复后编译匹配PACKAGE BODY仍报错的问题求助
- 执行以下SQL生成包含10000个过程的PACKAGE规范代码:
SELECT 'CREATE OR REPLACE PACKAGE test_me AS' FROM dual UNION ALL SELECT ' PROCEDURE test_procedure_' || ROWNUM || ';' FROM dual CONNECT BY ROWNUM <= 10000 UNION ALL SELECT 'END test_me;' FROM dual;
编译时报错:
[Error] Compilation (8198: 3): PLS-00123: program too large (Diana nodes)
- 编译简化后的有效PACKAGE规范:
CREATE OR REPLACE PACKAGE test_me AS PROCEDURE test_procedure_1; END test_me;
该规范编译成功,查询user_objects.status显示为'VALID'。
- 编译匹配的PACKAGE BODY:
CREATE OR REPLACE PACKAGE BODY test_me AS PROCEDURE test_procedure_1 AS BEGIN NULL; END; END test_me;
此时仍报错,除非先删除PACKAGE规范:
[Error] Compilation (1: 14): PLS-00905: object X.TEST_ME is invalid
PLS-00304: cannot compile body of 'TEST_ME' without its specification
求助:能否复现该问题?能否解释原因或提供解决方法?
能否复现
可以复现该问题。当尝试创建超大规模包规范触发PLS-00123错误后,即使后续替换为精简的有效包规范,编译包体时仍会触发上述错误,除非先删除原有的包对象。
原因解释
Oracle在处理包编译失败的场景时,会留下无效的字典元数据残留。第一次创建10000个过程的包规范时,编译失败导致Oracle内部的DIANA(Descriptive Intermediate Attributed Notation for Ada)节点处理溢出,此时虽然表面上没有创建出有效包,但字典中已经生成了该包的部分无效元数据。
后续创建精简的包规范时,虽然user_objects.status显示为VALID,但内部字典中的元数据可能仍存在损坏或不一致的情况。当编译包体时,Oracle会尝试关联包规范的元数据,发现这些残留的无效元数据后,就会抛出PLS-00905和PLS-00304错误,认为包规范不存在或无效。
解决方法
方法1:先删除包对象再重新创建
在编译精简的包规范前,先执行删除命令清理残留元数据:
DROP PACKAGE test_me;
之后重新创建精简的包规范,再编译包体即可成功。
方法2:强制重新验证包规范
如果不想删除包,可以执行以下命令强制Oracle重新验证包规范的元数据:
ALTER PACKAGE test_me COMPILE SPECIFICATION;
验证成功后再编译包体,可修复元数据不一致的问题。
方法3:拆分超大规模包
从根源上避免触发PLS-00123错误,Oracle对单个包的DIANA节点数量有内部限制,建议将大量过程拆分到多个独立包中,每个包保持合理的程序单元数量。
内容的提问来源于stack exchange,提问作者Peter Lang

