动态PL-SQL编程DBMS_SQL.PARSE触发ORA-00933错误求助
ORA-00933错误修复方案
核心错误点
- 绑定变量名非法:
WHERE MRUL = : OWL中: OWL中间存在空格,不符合Oracle绑定变量命名规则,需删除空格改为:OWL - 动态SQL拼接缺空格:循环拼接条件时,字段名、运算符、绑定变量、OR关键字之间未预留空格,会生成
CITY=:60OR这类非法语法 - 条件闭合逻辑错误:原
REGEXP_REPLACE会全局替换所有OR为),导致条件逻辑完全失效,需仅删除末尾多余的OR后补充闭合括号 - 绑定变量赋值错误:已查询到的
VAL变量未用于绑定,反而绑定了未赋值的空变量WS,不符合业务逻辑 - 测试数据语法错误:插入语句使用中文单引号
‘’,且CONTINENT字段值缺少闭合引号,无法正常执行
修正后PL/SQL代码
DECLARE SQLSTR VARCHAR2(30000); CUR INTEGER; SER INTEGER; VAL MRUL.OWL%TYPE; REFCUR SYS_REFCURSOR; TYPE ERMAS IS TABLE OF MRUL%ROWTYPE; -- 可根据实际查询的表调整行类型 SERULT ERMAS; CURSOR TION IS SELECT RUD.COL, RUD.VAL, RUD.OPR, RUD.RU3 FROM RMAP RUM, RDET RUD WHERE RUM.RU3 = RUD.RU3 AND RUD.RU3 IN ('60', '61', '62'); BEGIN CUR := DBMS_SQL.OPEN_CURSOR; -- 原DUAL表无自定义字段,此处根据业务逻辑调整为查询MRUL表 SQLSTR := 'SELECT * '||CHR(13); SQLSTR := SQLSTR || 'FROM MRUL '||CHR(13); SQLSTR := SQLSTR || 'WHERE OWL = :OWL AND ('; FOR DONC IN TION LOOP -- 各语法单元预留空格避免粘连报错 SQLSTR := SQLSTR || ' ' || DONC.COL || ' ' || DONC.OPR || ' :' || DONC.RU3 || ' OR '; END LOOP; -- 仅删除末尾多余的OR关键字,补充条件闭合括号 SQLSTR := RTRIM(SQLSTR, ' OR ') || ')'; DBMS_SQL.PARSE(CUR, SQLSTR, DBMS_SQL.NATIVE); SELECT OWL INTO VAL FROM MRUL WHERE RU2 = '20'; -- 绑定正确的查询结果变量 DBMS_SQL.BIND_VARIABLE(CUR, ':OWL', VAL); FOR DONC IN TION LOOP DBMS_SQL.BIND_VARIABLE(CUR, ':'|| DONC.RU3, DONC.VAL); END LOOP; SER := DBMS_SQL.EXECUTE(CUR); REFCUR := DBMS_SQL.TO_REFCURSOR(CUR); FETCH REFCUR BULK COLLECT INTO SERULT; END; /
修正后测试数据
CREATE TABLE RDET ( COL VARCHAR2(50) NOT NULL, VAL VARCHAR2(50) NOT NULL, OPR VARCHAR2(50) NOT NULL, RU3 VARCHAR2(50) NOT NULL ); CREATE TABLE RMAP ( RU2 VARCHAR2(50) NOT NULL, RU3 VARCHAR2(50) NOT NULL ); CREATE TABLE MRUL ( OWL VARCHAR2(50) NOT NULL, RU2 VARCHAR2(50) NOT NULL ); INSERT INTO RDET VALUES ('DELHI', 'CITY', '=', '60'); INSERT INTO RDET VALUES ('SHIMLA', 'VILLAGE', '<>', '61'); INSERT INTO RDET VALUES ('NOIDA', 'TOWN', '=', '62'); INSERT INTO RMAP VALUES ('20', '60'); INSERT INTO RMAP VALUES ('21', '61'); INSERT INTO RMAP VALUES ('21', '62'); INSERT INTO MRUL VALUES ('COUNTRY', '20'); INSERT INTO MRUL VALUES ('CONTINENT', '21'); INSERT INTO MRUL VALUES ('AREA', '22'); INSERT INTO MRUL VALUES ('AREA', '23');
内容的提问来源于stack exchange,提问作者Cool_Oracle
相关产品推荐
相关产品推荐

