PL/SQL代码从11g迁至19c易出问题,主因是语义规则收紧:FORALL空集合触发PLW-07203警告;UTL_FILE路径须用大写DIRECTORY对象;BOOLEAN不可直入SQL,需转CHAR/NUMBER;SQL%FOUND在混合DML+查询时行为异常,应改用显式游标。直接说结论:PL/SQL代码在11g能跑,迁到19c后大概率会报错或逻辑异常,不是语法写错了,而是语义规则收紧了。最常踩坑的四个点是
FORALL 空集合、UTL_FILE 路径、BOOLEAN 传入 SQL、SQL%FOUND 判定失效——每个都对应一个明确错误码,必须逐项处理。
FORALL 绑定空集合触发 PLW-07203 警告
11g 中 forall i in emp_ids.first..emp_ids.last 遇到 emp_ids.count = 0 时静默跳过;19c 在开启警告(如 plsql_warnings='enable:all')时抛 plw-07203,ci 流水线直接失败。
- 永远显式判断:
IF emp_ids.COUNT > 0 THEN FORALL i IN INDICES OF emp_ids ... END IF; - 别用
FIRST..LAST,改用INDICES OF或VALUES OF更安全 - 批量封装函数里尤其要加判断,不能依赖“反正没数据就不执行”这种隐式逻辑
UTL_FILE 报 ORA-29280:invalid directory path
11g 通过 UTL_FILE_DIR 参数放开任意 OS 路径;19c 废弃该参数,只认 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');(小写'ext_data_dir'会报ORA-22285) - 检查存量包体:
SELECT text FROM all_source WHERE upper(text) LIKE '%UTL_FILE%FOPEN%' AND owner = 'MY_APP';
BOOLEAN 变量进 SQL 报 PLS-00382:expression is of wrong type
11g 允许 WHERE flag = my_bool 这类写法;19c 彻底禁止,动态 SQL 尤其容易崩。
- 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 字段一致 - 别信注释里写的“此处传布尔值”,实际运行时类型校验更严
SELECT INTO 后 SQL%FOUND 返回上一条 DML 结果
11g 中 SQL%FOUND 总反映刚执行的 SELECT INTO;19c 会继承前一条 DML(比如 INSERT)的结果,导致误判“查到了”或“没查到”。
- 所有混合 DML + 查询的存储过程,必须把
SQL%FOUND换成显式游标 - 示例:
DECLARE CURSOR c IS SELECT ...; r c%ROWTYPE; BEGIN OPEN c; FETCH c INTO r; IF c%FOUND THEN ... END IF; - 别再依赖隐式游标属性做业务分支,这是最隐蔽的逻辑断裂点


















