14

我正在尝试使用绑定变量在动态 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 语句中使用绑定变量?

4

1 回答 1

25

DDL 语句中不允许绑定变量。所以以下语句会导致错误:

问题

要了解为什么会发生这种情况,我们需要查看如何处理动态 SQL 语句

通常,应用程序会提示用户输入 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'怎么办?
  • 示例#3:值NLS_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 || '''';
    
于 2014-08-25T15:10:49.607 回答