Oracle 动态SQL SELECT INTO返回可怕的ORA-00933:SQL命令未正确结束

Oracle 动态SQL SELECT INTO返回可怕的ORA-00933:SQL命令未正确结束,oracle,plsql,dynamic-sql,execute-immediate,select-into,Oracle,Plsql,Dynamic Sql,Execute Immediate,Select Into,我正在执行以下动态语句,并收到ORA-00933:SQL命令未正确结束: FUNCTION IsValidArchive RETURN BOOLEAN IS x BOOLEAN := TRUE; isValidArc_sql VARCHAR2(2000); BEGIN isValidArc_sql := 'SELECT COUNT(*), SUM(AMOUNT) ' || 'FROM ' || srcSche

我正在执行以下动态语句,并收到ORA-00933:SQL命令未正确结束:

FUNCTION IsValidArchive RETURN BOOLEAN
IS        
    x   BOOLEAN := TRUE;
    isValidArc_sql VARCHAR2(2000);
BEGIN
    isValidArc_sql := 'SELECT COUNT(*), SUM(AMOUNT) ' ||
                      'FROM ' || srcSchemaTable ||
                      ' WHERE TRUNC( ' || parm_rec.SRC_DATE_COLUMN || ' ) < ADD_MONTHS( ' ||
                                                      'ADD_MONTHS ( TRUNC (  NVL ( TO_DATE ( :parm_rec.SYS_OFFSET ) , SYSDATE) - ( :parm_rec.DAY_OFFSET )), ' ||
                                                      '( :parm_rec.MON_OFFSET * :kNEGATIVE ) ), ' ||
                                                      '( :parm_rec.YR_OFFSET * ( :kANNUM * :kNEGATIVE ) ) ); ';                                                                                                                                               
    EXECUTE IMMEDIATE isValidArc_sql
    INTO arc_cnt, arc_amt
    USING parm_rec.SYS_OFFSET, parm_rec.DAY_OFFSET, parm_rec.MON_OFFSET, kNEGATIVE, parm_rec.YR_OFFSET, kANNUM;

    IF arc_cnt > 0 AND arc_amt > 0 
        THEN x := TRUE;
    ELSE 
        x := FALSE;
    END IF;

    DBMS_OUTPUT.PUT_LINE( 'IsValidArchive: ' || CHR(10) ||
                          'Record Count - '  || arc_cnt || CHR(10) ||
                          'Total Amount - '  || arc_amt || CHR(13) );
    RETURN x;        
END IsValidArchive;
函数IsValidArchive返回布尔值
是
x布尔值:=真;
isValidArc_sql VARCHAR2(2000年);
开始
isValidArc_sql:=“选择计数(*),总和(金额)”||
“FROM”| | srcSchemaTable||
其中TRUNC(“| | parm_rec.SRC_DATE_COLUMN | |”)0且弧长>0
那么x:=真;
其他的
x:=假;
如果结束;
DBMS|u输出.PUT_行('IsValidArchive:'|| CHR(10)||
“记录计数-”||弧|cnt|CHR(10)||
“总金额-”| |弧| | | | CHR(13));
返回x;
结束语为有效达奇夫语;
如果我删除WHERE子句,这段代码将执行,这使我相信这可能是一个绑定变量问题。话虽如此,我在程序的另一部分中使用了相同的WHERE子句(这里减去一个bind变量),没有错误

我的绑定变量都填充了适当的值,语句中的文字看起来也正确

我的研究表明这种语法是正确的。我觉得问题出在哪里,很可能是绑定变量,但解决方案还没有显现出来。此代码在executeimmediate语句中出错

如果有人能指出我在这里做错了什么,我将不胜感激

谢谢

更新

感谢Kris和Alex指出我代码中的缺陷,下面是更正后的代码:

FUNCTION IsValidArchive RETURN BOOLEAN
IS        
    x   BOOLEAN := TRUE;
BEGIN
    isValidArc_sql := 'SELECT COUNT(*), SUM(AMOUNT) ' ||
                      'FROM ' || srcSchemaTable ||
                      ' WHERE TRUNC( createdate ) < ADD_MONTHS( ' ||
                                                      'ADD_MONTHS ( TRUNC (  NVL  ( :SYS_OFFSET  , SYSDATE ) - ( :DAY_OFFSET )), ' ||
                                                      '( :MON_OFFSET * :kNEGATIVE ) ), ' ||
                                                      '( :YR_OFFSET * ( :kANNUM * :kNEGATIVE ) ) ) ';                                                                                                                                               
    EXECUTE IMMEDIATE isValidArc_sql
    INTO arc_cnt, arc_amt
    USING parm_rec.SYS_OFFSET, parm_rec.DAY_OFFSET, parm_rec.MON_OFFSET, kNEGATIVE, parm_rec.YR_OFFSET, kANNUM, kNEGATIVE;

    IF arc_cnt > 0 AND arc_amt > 0
        THEN x := TRUE;
    ELSE 
        x := FALSE;
    END IF;
    DBMS_OUTPUT.PUT_LINE( 'IsValidArchive: ' || CHR(10) ||
                          'Record Count - '  || arc_cnt || CHR(10) ||
                          'Total Amount - '  || arc_amt || CHR(13) );
    RETURN x;        
END IsValidArchive;
函数IsValidArchive返回布尔值
是
x布尔值:=真;
开始
isValidArc_sql:=“选择计数(*),总和(金额)”||
“FROM”| | srcSchemaTable||
'其中TRUNC(createdate)<添加月份('||
'添加月份(TRUNC(NVL(:系统偏移,系统日期)-(:天偏移)),'||
“(:MON_OFFSET*:kNEGATIVE)),”||
“(:YR_OFFSET*(:kANNUM*:kNEGATIVE))”;
执行即时isValidArc_sql
分为弧长、弧长和弧长
使用parm_rec.SYS_OFFSET、parm_rec.DAY_OFFSET、parm_rec.MON_OFFSET、kNEGATIVE、parm_rec.YR_OFFSET、kANNUM、kNEGATIVE;
如果弧长>0且弧长>0
那么x:=真;
其他的
x:=假;
如果结束;
DBMS|u输出.PUT_行('IsValidArchive:'|| CHR(10)||
“记录计数-”||弧|cnt|CHR(10)||
“总金额-”| |弧| | | | CHR(13));
返回x;
结束语为有效达奇夫语;

正如@KrisRice所指出的,动态语句中不应该有尾随分号。这是SQL*Plus等中客户机定义的语句分隔符和/或终止符,但这是不同的上下文-在动态调用中只能有一条语句,因此它没有任何意义

然后您的绑定有点不正确。您似乎认为需要使用bind变量名来匹配
using
子句中的变量名,因此您可以使用
:parm\u rec.SYS\u OFFSET
之类的内容。这里的bind变量名实际上只是
parm\u rec
部分。请记住,生成的语句是在SQL上下文中执行的,而不是在PL/SQL上下文中执行的,因此句点被解释为schema.object.column模式的一部分,当句点之前的第一部分是变量时,这是没有意义的

:parm_rec
bind变量名与
parm_rec
PL/SQL记录名无关。你本可以同样有效地使用set的
:b0.SYS\u,这可能会使混淆更加清楚<代码>:b0
不是对象或参考,因此为ORA-22806

因此,将
:record.field
样式的引用更改为简单标识符,它仍然可以与匹配变量有一些名义关系,例如:

    isValidArc_sql := 'SELECT COUNT(*), SUM(AMOUNT) ' ||
                      'FROM ' || srcSchemaTable ||
                      ' WHERE TRUNC( ' || parm_rec.SRC_DATE_COLUMN || ' ) < ADD_MONTHS( ' ||
                                                      'ADD_MONTHS ( TRUNC (  NVL ( TO_DATE ( :SYS_OFFSET ) , SYSDATE) - ( :DAY_OFFSET )), ' ||
                                                      '( :MON_OFFSET * :kNEGATIVE ) ), ' ||
                                                      '( :YR_OFFSET * ( :kANNUM * :kNEGATIVE ) ) ) ';                                                                                                                                               
    EXECUTE IMMEDIATE isValidArc_sql
    INTO arc_cnt, arc_amt
    USING parm_rec.SYS_OFFSET, parm_rec.DAY_OFFSET, parm_rec.MON_OFFSET, kNEGATIVE, parm_rec.YR_OFFSET, kANNUM, kNEGATIVE;
isValidArc\u sql:='SELECT COUNT(*),SUM(AMOUNT)'||
“FROM”| | srcSchemaTable||
其中TRUNC(“| | parm_rec.SRC_DATE_COLUMN | |”)
我还添加了缺少的bind变量,在末尾重复了
kNEGATIVE
,因为它们都被引用了