为什么我不能在dynamicSQL中的DDL / SCL语句中使用绑定variables?
我正在尝试使用绑定variables在dynamicSQL中执行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
。
而我的问题是: 为什么我不能在dynamicSQL中的DDL / SCL语句中使用绑定variables?
在DDL语句中不允许绑定variables。 所以下面的语句会导致错误:
-
示例#1:DDL语句 。 将导致ORA-01027:绑定variables不允许进行数据定义操作
EXECUTE IMMEDIATE 'CREATE TABLE dummy_table ( dummy_column NUMBER DEFAULT :def_val )' USING 42;
-
示例#2:DDL语句 。 会导致ORA-00904::无效的标识符
EXECUTE IMMEDIATE 'CREATE TABLE dummy_table ( :col_name NUMBER )' USING var_col_name;
-
示例#3:SCL语句 。 将导致ORA-02248:ALTER SESSION无效选项
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_CALENDAR = :cal' USING var_calendar_option;
问题
要理解为什么发生这种情况,我们需要看看如何处理dynamicSQL语句 。
通常,应用程序会提示用户inputSQL语句的文本以及语句中使用的主机variables的值。 然后OracleparsingSQL语句。 也就是说,Oracle检查SQL语句以确保它遵循语法规则并引用有效的数据库对象。 parsing还包括检查数据库访问权限 1 ,预留所需的资源,并find最佳访问path。
1 回答者强调
请注意,parsing步骤在将任何variables绑定到dynamic语句之前发生。 如果您检查以上四个示例,您将意识到parsing器没有办法确保这些dynamicSQL语句的语法有效性,而无需知道绑定variables的值。
- 示例#1 :parsing器无法判断绑定值是否有效。 如果不
USING 42
,程序员用USING 'forty-two'
USING 42
写了什么? - 示例#2 :parsing器无法确定
:col_name
是否是有效的列名称。 如果绑定的列名是'identifier_that_well_exceeds_thirty_character_identifier_limit'
怎么办? - 例#3 :
NLS_CALENDAR
值是build立在常量(对于给定的Oracle版本?)。 parsing器不能分辨绑定variables是否有有效值。
所以答案就是你不能在dynamicSQL中绑定schema元素,比如表名,列名。 你也可以绑定build立在常量 。
解
实现dynamic引用模式元素/常量的唯一方法是在dynamicSQL语句中使用string连接。
-
示例#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 || '''';