Oracle存储过程遍历表列名集合时报PLS-00103编译错误
Oracle存储过程PLS-00103报错根因与修正
直接触发报错的核心原因
- 嵌套表遍历语法错误:原代码写为
FOR in_col IN input_cols,不符合PL/SQL语法规则。Oracle遍历嵌套表时,无法直接将集合变量放在FOR ... IN子句后,必须通过集合的索引属性定义遍历范围,语法匹配失败后,编译器解析到后续的LOOP关键字时触发当前报错。
其他隐藏的语法/逻辑问题
修正核心报错后,以下问题会陆续触发:
- 动态SQL拼接格式错误:原代码拼接的表名条件前后带多余空格,生成的查询条件为
TABLE_NAME = ' 传入表名 ',与数据字典中存储的无空格大写表名不匹配,无法查到列数据。 - BULK COLLECT INTO子句冗余语法:原代码给集合变量
input_cols额外加了外层括号,属于无效语法。 - 字典权限不适配:
DBA_TAB_COLUMNS需要高权限才能访问,查询普通用户下的表建议替换为USER_TAB_COLUMNS,同时需将传入的表名转大写,匹配字典的默认存储规则。 - 拼接式动态SQL存在注入风险:直接拼接表名的写法可被注入攻击,改用绑定变量更安全。
修正后可运行代码
CREATE OR REPLACE PROCEDURE map_values (mapping_table VARCHAR2(64)) AS TYPE col_names IS TABLE OF VARCHAR2(64); input_cols col_names; v_loop_idx PLS_INTEGER; BEGIN -- 使用绑定变量传递表名,避免注入和格式问题 EXECUTE IMMEDIATE 'SELECT COLUMN_NAME FROM USER_TAB_COLUMNS WHERE TABLE_NAME = :1' BULK COLLECT INTO input_cols USING UPPER(mapping_table); -- 处理空集合场景,避免空索引报错 IF input_cols.COUNT > 0 THEN v_loop_idx := input_cols.FIRST; WHILE v_loop_idx IS NOT NULL LOOP dbms_output.put_line('当前列名:' || input_cols(v_loop_idx)); v_loop_idx := input_cols.NEXT(v_loop_idx); END LOOP; END IF; END map_values; /
说明:如果需要跨用户查询表列,可将
USER_TAB_COLUMNS换回DBA_TAB_COLUMNS,同时增加OWNER的过滤参数,适配多场景查询需求。
内容的提问来源于stack exchange,提问作者shmail。
相关产品推荐
相关产品推荐

