Oracle 19c默认不启用PL/SQL编译警告,需执行ALTER SESSION SET PLSQL_WARNINGS='ENABLE:ALL'后重新编译对象,并查USER_ERRORS中ATTRIBUTE='WARNING'的记录;常见高危警告包括PLW-07203(空集合)、PLW-06009(异常吞没)、PLW-07204(隐式转换影响索引)等。

Oracle 19c 默认不启用 PL/SQL 编译警告(PLSQL_WARNINGS),所以你看到的“编译成功”很可能掩盖了未初始化变量、死代码、隐式类型转换等隐患——必须手动开启并检查。
如何启用并查看 PL/SQL 编译警告
警告不会阻断编译,但能暴露运行时才暴露的问题。关键不是开开关,而是确认它真在生效:
- 执行
ALTER SESSION SET PLSQL_WARNINGS = 'ENABLE:ALL';后再编译对象(不是只改代码就完事) - 查警告必须用
SELECT * FROM USER_ERRORS WHERE TYPE = 'PROCEDURE' AND NAME = 'YOUR_PROC' AND ATTRIBUTE = 'WARNING';——注意过滤ATTRIBUTE = 'WARNING',否则和错误混在一起 - 如果
USER_ERRORS里没警告记录,说明会话没设对,或对象是用 IDE 异步编译的(比如 SQL Developer 点“运行”不触发警告收集)
常见警告类型及真实风险点
不是所有警告都该忽略。以下几类在 19c 中已明确关联到性能或逻辑缺陷:
-
PLW-06002: Unreachable code:通常出现在RETURN后还有语句,但更危险的是在异常块中写了RAISE又跟了赋值——19c 优化器可能跳过后续逻辑,导致监控变量没更新 -
PLW-05003: Subprogram name is never used:若该子程序被PRAGMA INLINE标记,而实际未被内联,说明优化条件不满足(比如含DBMS_OUTPUT),此时警告比执行计划更早暴露问题 -
PLW-07203: Parameter may not be used:参数未参与任何计算,但被传入动态 SQL 字符串拼接——这往往是 SQL 注入漏洞的温床,不是冗余,是安全隐患 -
PLW-06009: Procedure 'XXX' OTHERS handler does not end in RAISE or RAISE_APPLICATION_ERROR:静默吞掉异常后继续执行,19c 的自适应计划可能因统计信息偏差误判后续 SQL 路径
警告与优化器行为的隐性耦合
19c 的 CBO 会读取 PL/SQL 编译元数据辅助估算,某些警告直接干扰执行计划生成:
- 出现
PLW-06010: Keyword 'NOCOPY' specified for parameter without warning但没加NOCOPY,大集合传参时 PGA 使用量可能被低估,导致并行度决策失准 -
PLW-07204: Conversion away from column type may affect index usage表示 WHERE 条件中对索引列做了隐式转换(如TO_CHAR(empno)),19c 即使有函数索引也大概率不走 - 带
DETERMINISTIC的函数若触发PLW-06008: Function result might not be deterministic,CBO 会放弃谓词下推,强制先算函数再过滤
别信 IDE 的“无警告提示”
很多工具(SQL Developer、Toad)只显示语法级警告,漏掉语义级问题:
- 它们默认不启用
ENABLE:PORTABILITY和ENABLE:PERFORMANCE,而这俩对 19c 的批量处理(FORALL、BULK COLLECT)最关键 - 检查是否启用完整警告集:
SELECT VALUE FROM V$PARAMETER WHERE NAME = 'plsql_warnings';,返回值应为ENABLE:ALL,而非空或DISABLE:ALL - 最可靠方式是脚本化编译:用 SQL*Plus 执行
ALTER PROCEDURE p COMPILE PLSQL_WARNINGS='ENABLE:ALL';后立刻查USER_ERRORS,绕过 IDE 缓存
警告本身不报错,但每一条都对应一个 Oracle 内部校验失败点;19c 的执行计划稳定性高度依赖这些元数据的准确性——忽略警告,等于主动放弃优化器的可信输入。


















