当我尝试 运行 我编写的 Oracle 存储过程时出现 ORA-00933: SQL 命令未正确结束错误
Getting a ORA-00933: SQL command not properly ended error when I try to run an Oracle stored procedure that I wrote
作为项目的一部分,我正在研究我们公司使用的 peoplesoft 记录和字段的数据映射。我必须记录超过 25,000 个字段,但它变得乏味,并且比我以正常方式完成时花费的时间要多得多。所以,我写了一个存储过程来减少记录翻译值的一些工作。
这是我的存储过程的代码:
CREATE OR REPLACE PROCEDURE SP_DATAMAPPINGINFO AS
TYPE EmpCurTyp IS REF CURSOR;
newrow_cursor EmpCurTyp;
txtable_cursor EmpCurTyp;
recname varchar2(30);
recdescr varchar2(200);
fieldnum number(3);
fieldname varchar2(30);
fieldescr varchar2(2000);
keyflag varchar2(1);
fieldtype varchar2(20);
distinctcount number(10);
query1_str varchar(300);
query2_str varchar(300);
query3_str varchar(300);
fieldvalue varchar2(200);
hyphen varchar2(5);
txvalue varchar2(200);
fielduse varchar2(500);
tablename varchar2(40);
intertxtabname varchar2(30);
txtablename varchar2(40);
CURSOR get_fields is
select A.RECNAME as "Record", A.RECDESCR as "Record Description"
, B.FIELDNUM as "FieldNum", B.FIELDNAME as "Field", C.DESCRLONG as "Field Description", CASE WHEN
EXISTS(select K.FIELDNAME FROM PSRECFLDDBKEYVW K WHERE K.RECNAME = A.RECNAME AND K.FIELDNAME=B.FIELDNAME)
THEN 'Y' ELSE 'N' END as "Key (Y/N)", DECODE (C.FIELDTYPE,
0, 'Character',
1, 'Long Char',
2, 'Number',
3, 'Signed Number',
4, 'Date',
5, 'Time',
6, 'DateTime',
8, 'Image/ Attachment',
9, 'Image Reference',
'Unknown') as "FieldType"
FROM PSRECDEFN A, PSRECFIELDDB B LEFT JOIN PSDBFIELD C ON (B.FIELDNAME = C.FIELDNAME)
WHERE B.RECNAME = A.RECNAME
AND A.RECNAME IN (select R.RECNAME from PSRECDEFN R, DBA_TABLES T
WHERE ('PS_'||R.RECNAME=T.TABLE_NAME)
AND T.NUM_ROWS > 0
AND R.RECTYPE=0)
order by A.RECNAME, B.FIELDNUM;
BEGIN
OPEN get_fields;
LOOP
FETCH get_fields INTO recname, recdescr, fieldnum, fieldname, fieldescr, keyflag, fieldtype;
fielduse := '';
tablename := 'PS_' || recname;
hyphen := ' - ';
fieldvalue := '';
txvalue := '';
intertxtabname := '';
txtablename := '';
if (fieldname <> '%EMPLID%' and fieldname <> '%DESCR%' and fieldname <> '%COMMENT%') THEN
query1_str := 'select RI.EDITTABLE FROM PSRECDEFN RD, PSRECFIELDDB RI WHERE RD.RECNAME = RI.RECNAME
AND RD.RECNAME = ' || recname || 'AND RI.FIELDNAME = ' || fieldname;
OPEN txtable_cursor FOR query1_str;
FETCH txtable_cursor INTO intertxtabname;
CLOSE txtable_cursor;
query2_str := 'select count(distinct T.' || fieldname || ') FROM ' || tablename;
IF (intertxtabname IS NOT NULL) THEN
txtablename := 'PS_' || intertxtabname;
query3_str := 'select distinct T.' || fieldname || ', TR.DESCR FROM ' || tablename || ' T left join ' || txtablename || ' TR ON T.'
|| fieldname || ' = TR.' || fieldname || ' order by T.' || fieldname;
ELSE
txtablename := '';
query3_str := 'select distinct DT.' || fieldname || ', DTR.XLATLONGNAME FROM ' || tablename || ' DT left join PSXLATITEM DTR on
(DTR.FIELDNAME = ''' || fieldname || ''' and DT.' || fieldname || ' = DTR.FIELDVALE) order by DT.' || fieldname;
END IF;
execute immediate query2_str into distinctcount;
if(distinctcount > 150) THEN
fielduse := 'More than 150';
ELSE
OPEN newrow_cursor FOR query3_str USING 'fieldname';
LOOP
FETCH newrow_cursor INTO fieldvalue, txvalue;
fielduse := fieldvalue || ' - ' || txvalue;
EXIT WHEN newrow_cursor%NOTFOUND;
END LOOP;
CLOSE newrow_cursor;
END IF;
ELSE
fielduse := 'SKIPPING';
END IF;
dbms_output.put_line(recname || ',' || recdescr || ',' || fieldnum || ',' || fieldname || ',' || fieldescr || ',' || keyflag || ',' || fieldtype || ',' || fielduse);
END LOOP;
CLOSE get_fields;
NULL;
END SP_DATAMAPPINGINFO;
存储过程编译没有任何错误,但是当我执行它时,出现以下错误:
Error starting at line : 1 in command -
BEGIN SP_DATAMAPPINGINFO; END;
Error report -
ORA-00933: SQL command not properly ended
ORA-06512: at "SYSADM.SP_DATAMAPPINGINFO", line 69
ORA-06512: at line 1
- 00000 - "SQL command not properly ended"
*Cause:
*Action:
存储过程中的第 69 行是 OPEN txtable_cursor FOR query1_str;
我试过使用绑定变量,但仍然出现错误,我可能使用不当。
我的代码可能还有其他问题。如果你能指出这些就太好了。我们目前在 Oracle 12c
Line 69 in the stored proc is OPEN txtable_cursor FOR query1_str;
.
显然我们无法 运行 您的代码,因为我们没有您的架构,因此我们无法编译和验证您的动态 SQL。但是,查看您组装的字符串,引人注目的是样板文本和列的串联:
AND RD.RECNAME = ' || recname || 'AND RI.FIELDNAME = ' || fieldname
如果仔细观察,您会发现 'AND RI.FIELDNAME
中的引号后没有 space,这意味着 recname
的值与 AND
连接在一起。那就是你的 ORA-00933。
一旦你解决了这个问题,你可能会 运行 变成 ORA-00936: missing expression
。从变量声明中我们知道 recname
和 fieldname
是字符串,但 你没有将它们视为字符串 。该代码不包含变量周围的任何引号,因此执行的查询会将它们视为列或其他内容。所以这是你需要解决的问题:
AND RD.RECNAME = ''' || recname || ''' AND RI.FIELDNAME = ''' || fieldname ||''''
稍后您可以这样打开游标:
OPEN newrow_cursor FOR query3_str USING 'fieldname';
所以您将参数传递给不包含任何参数占位符的动态查询。那应该抛出
ORA-01006: bind variable does not exist
动态SQL很难,因为它将编译错误转化为运行时间错误。您需要培养冷静的眼光来查看您的代码以发现它们。有用的一件事是使用日志记录来记录动态语句(DBMS_OUTPUT 总比没有好)。通常当我们眼前有真实的陈述时,很容易发现我们的灯笼裤。但如果我们不能,至少我们可以 运行 查询并让编译器指出它们。
作为项目的一部分,我正在研究我们公司使用的 peoplesoft 记录和字段的数据映射。我必须记录超过 25,000 个字段,但它变得乏味,并且比我以正常方式完成时花费的时间要多得多。所以,我写了一个存储过程来减少记录翻译值的一些工作。
这是我的存储过程的代码:
CREATE OR REPLACE PROCEDURE SP_DATAMAPPINGINFO AS
TYPE EmpCurTyp IS REF CURSOR;
newrow_cursor EmpCurTyp;
txtable_cursor EmpCurTyp;
recname varchar2(30);
recdescr varchar2(200);
fieldnum number(3);
fieldname varchar2(30);
fieldescr varchar2(2000);
keyflag varchar2(1);
fieldtype varchar2(20);
distinctcount number(10);
query1_str varchar(300);
query2_str varchar(300);
query3_str varchar(300);
fieldvalue varchar2(200);
hyphen varchar2(5);
txvalue varchar2(200);
fielduse varchar2(500);
tablename varchar2(40);
intertxtabname varchar2(30);
txtablename varchar2(40);
CURSOR get_fields is
select A.RECNAME as "Record", A.RECDESCR as "Record Description"
, B.FIELDNUM as "FieldNum", B.FIELDNAME as "Field", C.DESCRLONG as "Field Description", CASE WHEN
EXISTS(select K.FIELDNAME FROM PSRECFLDDBKEYVW K WHERE K.RECNAME = A.RECNAME AND K.FIELDNAME=B.FIELDNAME)
THEN 'Y' ELSE 'N' END as "Key (Y/N)", DECODE (C.FIELDTYPE,
0, 'Character',
1, 'Long Char',
2, 'Number',
3, 'Signed Number',
4, 'Date',
5, 'Time',
6, 'DateTime',
8, 'Image/ Attachment',
9, 'Image Reference',
'Unknown') as "FieldType"
FROM PSRECDEFN A, PSRECFIELDDB B LEFT JOIN PSDBFIELD C ON (B.FIELDNAME = C.FIELDNAME)
WHERE B.RECNAME = A.RECNAME
AND A.RECNAME IN (select R.RECNAME from PSRECDEFN R, DBA_TABLES T
WHERE ('PS_'||R.RECNAME=T.TABLE_NAME)
AND T.NUM_ROWS > 0
AND R.RECTYPE=0)
order by A.RECNAME, B.FIELDNUM;
BEGIN
OPEN get_fields;
LOOP
FETCH get_fields INTO recname, recdescr, fieldnum, fieldname, fieldescr, keyflag, fieldtype;
fielduse := '';
tablename := 'PS_' || recname;
hyphen := ' - ';
fieldvalue := '';
txvalue := '';
intertxtabname := '';
txtablename := '';
if (fieldname <> '%EMPLID%' and fieldname <> '%DESCR%' and fieldname <> '%COMMENT%') THEN
query1_str := 'select RI.EDITTABLE FROM PSRECDEFN RD, PSRECFIELDDB RI WHERE RD.RECNAME = RI.RECNAME
AND RD.RECNAME = ' || recname || 'AND RI.FIELDNAME = ' || fieldname;
OPEN txtable_cursor FOR query1_str;
FETCH txtable_cursor INTO intertxtabname;
CLOSE txtable_cursor;
query2_str := 'select count(distinct T.' || fieldname || ') FROM ' || tablename;
IF (intertxtabname IS NOT NULL) THEN
txtablename := 'PS_' || intertxtabname;
query3_str := 'select distinct T.' || fieldname || ', TR.DESCR FROM ' || tablename || ' T left join ' || txtablename || ' TR ON T.'
|| fieldname || ' = TR.' || fieldname || ' order by T.' || fieldname;
ELSE
txtablename := '';
query3_str := 'select distinct DT.' || fieldname || ', DTR.XLATLONGNAME FROM ' || tablename || ' DT left join PSXLATITEM DTR on
(DTR.FIELDNAME = ''' || fieldname || ''' and DT.' || fieldname || ' = DTR.FIELDVALE) order by DT.' || fieldname;
END IF;
execute immediate query2_str into distinctcount;
if(distinctcount > 150) THEN
fielduse := 'More than 150';
ELSE
OPEN newrow_cursor FOR query3_str USING 'fieldname';
LOOP
FETCH newrow_cursor INTO fieldvalue, txvalue;
fielduse := fieldvalue || ' - ' || txvalue;
EXIT WHEN newrow_cursor%NOTFOUND;
END LOOP;
CLOSE newrow_cursor;
END IF;
ELSE
fielduse := 'SKIPPING';
END IF;
dbms_output.put_line(recname || ',' || recdescr || ',' || fieldnum || ',' || fieldname || ',' || fieldescr || ',' || keyflag || ',' || fieldtype || ',' || fielduse);
END LOOP;
CLOSE get_fields;
NULL;
END SP_DATAMAPPINGINFO;
存储过程编译没有任何错误,但是当我执行它时,出现以下错误:
Error starting at line : 1 in command -
BEGIN SP_DATAMAPPINGINFO; END;
Error report -
ORA-00933: SQL command not properly ended
ORA-06512: at "SYSADM.SP_DATAMAPPINGINFO", line 69
ORA-06512: at line 1
- 00000 - "SQL command not properly ended"
*Cause:
*Action:
存储过程中的第 69 行是 OPEN txtable_cursor FOR query1_str;
我试过使用绑定变量,但仍然出现错误,我可能使用不当。
我的代码可能还有其他问题。如果你能指出这些就太好了。我们目前在 Oracle 12c
Line 69 in the stored proc is
OPEN txtable_cursor FOR query1_str;
.
显然我们无法 运行 您的代码,因为我们没有您的架构,因此我们无法编译和验证您的动态 SQL。但是,查看您组装的字符串,引人注目的是样板文本和列的串联:
AND RD.RECNAME = ' || recname || 'AND RI.FIELDNAME = ' || fieldname
如果仔细观察,您会发现 'AND RI.FIELDNAME
中的引号后没有 space,这意味着 recname
的值与 AND
连接在一起。那就是你的 ORA-00933。
一旦你解决了这个问题,你可能会 运行 变成 ORA-00936: missing expression
。从变量声明中我们知道 recname
和 fieldname
是字符串,但 你没有将它们视为字符串 。该代码不包含变量周围的任何引号,因此执行的查询会将它们视为列或其他内容。所以这是你需要解决的问题:
AND RD.RECNAME = ''' || recname || ''' AND RI.FIELDNAME = ''' || fieldname ||''''
稍后您可以这样打开游标:
OPEN newrow_cursor FOR query3_str USING 'fieldname';
所以您将参数传递给不包含任何参数占位符的动态查询。那应该抛出
ORA-01006: bind variable does not exist
动态SQL很难,因为它将编译错误转化为运行时间错误。您需要培养冷静的眼光来查看您的代码以发现它们。有用的一件事是使用日志记录来记录动态语句(DBMS_OUTPUT 总比没有好)。通常当我们眼前有真实的陈述时,很容易发现我们的灯笼裤。但如果我们不能,至少我们可以 运行 查询并让编译器指出它们。