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

sam*_*ris 14 oracle plsql dynamic-sql execute-immediate

我试图在动态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;
Run Code Online (Sandbox Code Playgroud)

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

Test_Pkg.Set_Nls_Calendar('Thai Buddha');
Run Code Online (Sandbox Code Playgroud)

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

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

sam*_*ris 24

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语句中使用字符串连接.