【问题标题】:Why cannot I use bind variables in DDL/SCL statements in dynamic SQL?为什么我不能在动态 SQL 的 DDL/SCL 语句中使用绑定变量?
【发布时间】:2014-10-18 18:51:58
【问题描述】:

我正在尝试使用绑定变量在动态 SQL 中执行 SQL 命令:

-- this procedure is a part of PL/SQL package Test_Pkg
PROCEDURE Set_Nls_Calendar(calendar_ IN VARCHAR2)
IS
BEGIN
   EXECUTE IMMEDIATE
      'ALTER SESSION
      SET NLS_CALENDAR = :cal'
      USING IN calendar_;
END Set_Nls_Calendar;

然后在客户端,我尝试调用该过程:

Test_Pkg.Set_Nls_Calendar('Thai Buddha');

但这就是我ORA-02248: invalid option for ALTER SESSION

我的问题是:为什么我不能在动态 SQL 的 DDL/SCL 语句中使用绑定变量?

【问题讨论】:

    标签: oracle plsql dynamic-sql execute-immediate


    【解决方案1】:

    DDL 语句中不允许绑定变量。所以下面的语句会报错:

    问题

    要了解为什么会发生这种情况,我们需要查看How Dynamic SQL Statements Are Processed

    通常,应用程序会提示用户输入 SQL 语句的文本和语句中使用的主变量的值。然后 Oracle 解析 SQL 语句。也就是说,Oracle 检查 SQL 语句以确保它遵循语法规则并且 引用有效的数据库对象。解析还涉及检查数据库访问权限1、保留所需资源以及找到最佳访问路径。

    1回答者添加的重点

    请注意,解析步骤发生在将任何变量绑定到动态语句之前。如果您检查上述四个示例,您会发现解析器无法在不知道绑定变量的值的情况下保证这些动态 SQL 语句的语法有效性。

    • 示例 #1:解析器无法判断绑定值是否有效。如果程序员写的不是USING 42,而是USING 'forty-two',该怎么办?
    • 示例 #2:解析器无法判断 :col_name 是否是有效的列名。如果绑定的列名是'identifier_that_well_exceeds_thirty_character_identifier_limit'怎么办?
    • 示例 #3NLS_CALENDAR 的值内置在常量中(对于给定的 Oracle 版本?)。解析器无法判断绑定变量是否具有有效值。

    所以答案是不能在动态SQL中绑定表名、列名等模式元素。你也不能绑定内置常量


    解决方案

    实现动态引用架构元素/常量的唯一方法是在动态 SQL 语句中使用字符串连接。

    • 示例 #1:

      EXECUTE IMMEDIATE
        'CREATE TABLE dummy_table ( dummy_column NUMBER DEFAULT ' || to_char(42) || ')';
      
    • 示例 #2:

      EXECUTE IMMEDIATE
        'CREATE TABLE dummy_table (' || var_col_name || ' NUMBER )';
      
    • 示例 #3:

      EXECUTE IMMEDIATE
        'ALTER SESSION SET NLS_CALENDAR = ''' || var_calendar_option || '''';
      

    【讨论】:

    • 非常好。汤姆在这里也讨论了这个asktom.oracle.com/pls/apex/…
    • 我需要使用用户提供的密码进行ALTER USER,但是字符串连接会引入SQL注入攻击。
    • @RayCheng:你显然需要清理用户输入。
    猜你喜欢
    • 1970-01-01
    • 2012-05-31
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    • 1970-01-01
    • 2012-02-11
    • 1970-01-01
    • 2018-05-20
    相关资源
    最近更新 更多