结论:11g存储过程在19c里不是“不能跑”,而是“可能跑偏”——执行计划变、隐式转换收紧、权限模型升级,导致结果错、性能崩、甚至ora-00904报错;必须针对性重检,不能只靠编译通过。
直接说结论:11g存储过程在19c里不是“不能跑”,而是“可能跑偏”——执行计划变、隐式转换收紧、权限模型升级,导致结果错、性能崩、甚至ora-00904报错。必须针对性重检,不能只靠编译通过。
查出哪些存储过程会因优化器行为变化失效
19c默认启用optimizer_features_enable='19.1.0',旧执行计划可能被彻底丢弃。尤其当过程里含复杂DECODE嵌套(超10层)、UNION ALL带子查询、或依赖ROWNUM做分页时,执行计划常跳变。
- 运行
DBMS_SQLTUNE.CREATE_TUNING_TASK对核心过程预演:指定scope => 'COMPREHENSIVE',强制用19c优化器重解析 - 检查
V$SQL_PLAN中同一sql_id在11g和19c下的operation和options是否一致,重点盯NESTED LOOPS→HASH JOIN类变更 - 避免临时改
optimizer_features_enable回退——这是掩耳盗铃,掩盖了真实适配问题
修复DATE算术运算和隐式类型转换报错
11g里SYSDATE - date_col > 30能跑,19c默认开启SQL92_SECURITY=TRUE后,若调用者没SELECT权限,直接ORA-00942;更隐蔽的是TO_CHAR(date_col, 'YYYY')在19c里若date_col为NULL且上下文期望VARCHAR2,可能触发ORA-06502。
- 所有涉及
DATE的算术表达式,显式加TRUNC或CAST:比如改SYSDATE - date_col为TRUNC(SYSDATE) - TRUNC(date_col) - 禁用隐式转换:在过程头部加
PRAGMA AUTONOMOUS_TRANSACTION无用,真正要设ALTER SESSION SET SQL_MODE='STRICT_TRANS_TABLES'(虽Oracle不叫SQL_MODE,但等效逻辑是收紧NLS_DATE_FORMAT和CAST规则) - 检查
ALL_ARGUMENTS中data_type为DATE的参数,确认调用方传入的字面量是否带时区(如TIMESTAMP WITH TIME ZONE),19c对此更敏感
重编译前先清理UTL_FILE等外部依赖
很多11g过程用UTL_FILE.FOPEN写日志,但19c要求CREATE DIRECTORY对象必须存在且GRANT READ,WRITE ON DIRECTORY显式授权给过程所有者——仅DBA角色不够。
- 查未授权目录:
SELECT * FROM DBA_TAB_PRIVS WHERE TABLE_NAME IN (SELECT DIRECTORY_NAME FROM DBA_DIRECTORIES) AND GRANTEE = '<code>YOUR_PROC_OWNER' - 若过程所有者是
SCOTT,执行:GRANT READ,WRITE ON DIRECTORY DATA_PUMP_DIR TO SCOTT(别用UTL_FILE_DIR参数,该参数19c已废弃) -
UTL_HTTP调用需检查ACL:运行DBMS_NETWORK_ACL_ADMIN.CHECK_PRIVILEGE确认connect权限是否绑定到目标域名
最易被忽略的点是:utlrp.sql重编译只解决语法兼容,不解决语义漂移。一个编译成功的存储过程,在19c里可能返回错误结果——因为统计信息陈旧、绑定变量窥探行为变化、甚至RESULT_CACHE缓存键计算逻辑已不同。上线前必须用真实业务数据集压测,而非只跑EXEC看是否报错。











