为啥会出现“ORA-00933:SQL 命令未正确结束”错误(立即执行)?

Posted

技术标签:

【中文标题】为啥会出现“ORA-00933:SQL 命令未正确结束”错误(立即执行)?【英文标题】:Why do I get "ORA-00933: SQL command not properly ended" error ( execute immediate )?为什么会出现“ORA-00933:SQL 命令未正确结束”错误(立即执行)? 【发布时间】:2021-11-30 16:02:09 【问题描述】:

我创建了一个函数,它使用动态 sql:

create function check_ref_value
(
    table_name varchar2,
    code_value number,
    code_name  varchar2
) return number is
    l_query varchar2(32000 char);
    l_res   number;
begin
    l_query := '
        select sign(count(1))
        into :l_res
        from '|| table_name ||'
        where '|| code_name ||' = :code_value
    ';

    execute immediate l_query
    using in code_value, out l_res;

    return l_res;
end;

但是当我尝试使用它时,我得到一个异常“ORA-00933:SQL 命令未正确结束” 这段代码有什么问题?

【问题讨论】:

【参考方案1】:

您可以使用EXECUTE IMMEDIATE ... INTO ... USING ... 获取返回值,使用DBMS_ASSERT 在SQL 注入尝试的情况下引发错误:

create function check_ref_value
(
    table_name varchar2,
    code_value number,
    code_name  varchar2
) return number is
    l_query varchar2(32000 char);
    l_res   number;
begin
    l_query := 'select sign(count(1))'
            || ' from  ' || DBMS_ASSERT.SIMPLE_SQL_NAME(table_name)
            || ' where ' || DBMS_ASSERT.SIMPLE_SQL_NAME(code_name)
            || ' = :code_value';
    execute immediate l_query INTO l_res USING code_value;

    return l_res;
end;
/

其中,对于样本数据:

CREATE TABLE abc (a, b, c) AS
SELECT 1, 42, 3.14159 FROM DUAL;

然后:

SELECT CHECK_REF_VALUE('abc', 42, 'b') AS chk FROM DUAL;

输出:

CHK
1

还有:

SELECT CHECK_REF_VALUE('abc', 42, '1 = 1 OR b') AS chk FROM DUAL;

引发异常:

ORA-44003: invalid SQL name
ORA-06512: at "SYS.DBMS_ASSERT", line 160
ORA-06512: at "FIDDLE_UVOFONEFDEHGDQJELQJL.CHECK_REF_VALUE", line 10

至于你的问题:

这段代码有什么问题?

使用SELECT ... INTO 仅在PL/SQL 块中的SQL 语句中有效,并且当您通过EXECUTE IMMEDIATE 运行该语句时,它在SQL 范围内而不是PL/SQL 范围内执行。

您可以通过将动态代码包装在 BEGIN .. END PL/SQL 匿名块中来修复它(并颠倒 USING 子句中绑定参数的顺序):

create function check_ref_value
(
    table_name varchar2,
    code_value number,
    code_name  varchar2
) return number is
    l_query varchar2(32000 char);
    l_res   number;
begin
    l_query := '
      BEGIN
        select sign(count(1))
        into :l_res
        from '|| DBMS_ASSERT.SIMPLE_SQL_NAME(table_name) ||'
        where '|| DBMS_ASSERT.SIMPLE_SQL_NAME(code_name) ||' = :code_value;
      END;
    ';

    execute immediate l_query
    using out l_res, in code_value;

    return l_res;
end;
/

(但是,这比使用EXECUTE IMMEDIATE ... INTO ... USING ... 更复杂一些。)

db小提琴here

【讨论】:

以上是关于为啥会出现“ORA-00933:SQL 命令未正确结束”错误(立即执行)?的主要内容,如果未能解决你的问题,请参考以下文章

ORA-00933: SQL 命令未正确结束 00933. 00000 - “SQL 命令未正确结束

SQL 错误:ORA-00933:SQL 命令未正确结束 00933。00000 -“SQL 命令未正确结束”

“ORA-00933: SQL 命令未正确结束”

ora-00933:SQL 命令未正确结束

ORA-00933: SQL 命令未正确结束异常

SQL 中的 PIVOT 给出错误 - ORA-00933: SQL 命令未正确结束