oracle 19c迁移需重点处理四类隐性问题:forall空集合触发plw-07203警告,须显式检查count;utl_file路径须改用directory对象;sql中boolean类型禁用隐式转换,需转为char/number;sql%found在混合dml与查询中易误判,应改用no_data_found异常捕获。

FORALL绑定空集合触发PLW-07203警告
Oracle 11g允许FORALL在集合为空时静默跳过,19c仍兼容该行为,但开启plsql_warnings='enable:all'或使用PRAGMA WARNING时会报PLW-07203警告。CI流水线或严格校验环境常因此失败。
- 显式检查集合长度:
IF emp_ids.COUNT > 0 THEN FORALL i IN INDICES OF emp_ids ... END IF; - 避免在批量DML封装函数中依赖隐式跳过逻辑
- 迁移后扫描存量代码:
SELECT * FROM all_plsql_object_settings WHERE warning_setting LIKE '%PLW-07203%';
UTL_FILE路径访问报ORA-29280错误
UTL_FILE_DIR参数在19c已废弃,硬编码路径会直接触发ORA-29280: invalid directory path。必须改用CREATE DIRECTORY对象并授权。
- 创建目录对象:
CREATE DIRECTORY ext_data_dir AS '/u01/app/oracle/extdata'; - 授予权限:
GRANT READ, WRITE ON DIRECTORY ext_data_dir TO my_app_user; - 代码中改用目录名(注意大小写):
f := UTL_FILE.FOPEN('EXT_DATA_DIR', 'log.txt', 'W');
BOOLEAN类型在SQL中报PLS-00382错误
11g允许WHERE flag = my_bool这类隐式转换,19c彻底禁止,报PLS-00382: expression is of wrong type。这是最隐蔽的断裂点,常见于EXECUTE IMMEDIATE拼接场景。
- SQL层统一用
CHAR(1)或NUMBER(1)代替BOOLEAN传参 - 封装转换函数:
FUNCTION bool_to_yn(b BOOLEAN) RETURN CHAR IS BEGIN RETURN CASE WHEN b THEN 'Y' ELSE 'N' END; END; - 逐行检查所有
EXECUTE IMMEDIATE语句,确认绑定变量类型与SQL期望一致
SQL%FOUND在混合DML+查询中误判
19c中SQL%FOUND反映的是上一条DML(如INSERT)的结果,而非紧邻的SELECT INTO——若先执行DML再查数据,SQL%FOUND可能为TRUE而实际未查到数据。
- 不要跨语句复用
SQL%FOUND,每个SELECT INTO后立即判断 - 改用
NO_DATA_FOUND异常捕获更可靠:BEGIN SELECT ... INTO ...; EXCEPTION WHEN NO_DATA_FOUND THEN ... END; - 尤其注意存储过程中DML与查询混排的逻辑块,需插入显式重置或分段处理
迁移到19c后,真正难排查的不是语法报错,而是那些不报错却逻辑偏移的行为——比如SQL%FOUND值被前一条语句污染,或者BOOLEAN在动态SQL里悄悄转成NULL。这些点不会立刻崩,但会在特定数据分支下突然失效。











