为啥我不能在立即执行语句中使用绑定变量?
Posted
技术标签:
【中文标题】为啥我不能在立即执行语句中使用绑定变量?【英文标题】:Why I can't use a bind variable in an execute immediate statement?为什么我不能在立即执行语句中使用绑定变量? 【发布时间】:2011-08-02 05:23:16 【问题描述】:当我为execute immediate
构建动态 SQL 语句时,我想使用绑定变量而不是字符串连接。
在下面的示例中,我可以为a
、b
和ret
使用绑定变量,但是当我尝试为f
绑定时,我得到一个ORA-06502: PL/SQL: numeric or value error: character to number conversion error
。为什么以及如何绑定f
?
我使用的是 11.2.0.1.0。
create or replace function so4fun (
a in number,
b in number,
f in varchar2
) return number as
decl constant varchar2(32767) :=
'declare a constant number := :a; b constant number := :b;';
stmt varchar2(32676);
ret number;
begin
/* This one works: */
stmt := decl || ' begin :result := ' || f || '; end;';
execute immediate stmt using in a, in b, out ret;
/* But why this one doesn't ?
stmt := decl || ' begin :result := :f; end;';
execute immediate stmt using in a, in b, out ret, in f;
This doesn't work either:
stmt := decl || ' tmp number; begin tmp := :f; :result := tmp; end;';
execute immediate stmt using in a, in b, in f, out ret;
Both are giving me ORA-06502: PL/SQL: numeric or value error: character to
number conversion error */
return ret;
end;
/
show errors
/* expected result when a = 1, b = 2 is 1.5 */
select so4fun(1, 2, '(a + b) / b') from dual;
drop function so4fun;
【问题讨论】:
我选择了 Codo 的答案,因为我看到他的答案更全面、更紧凑。但是,我也发现 Ray Toal 的回答很有用,我也可以从他的回答中得出我的问题的答案。希望大家多多点赞! 【参考方案1】:绑定变量用于绑定变量,而不是用于绑定代码片段。这个想法是,Oracle 可以编译和缓存一个查询或代码块,并使用不同的参数多次执行它。
但是,您尝试使用参数绑定来替换计算公式。它会阻止编译和缓存代码块,因此不受支持。
此外,它不能用当前的语法来表达。如果 Oracle 看到tmp := :f
,它认为您只是想将参数f
分配给变量tmp
。它不需要评估函数。
只需使用可行的解决方案即可。毕竟它有效。
【讨论】:
【参考方案2】:发生错误是因为您将f
声明为varchar2
,但您在注释掉的部分中写了以下内容:
tmp number; begin tmp := :f ...
您尝试将“字符”值分配给需要数字的变量。您还尝试将 f
分配给再次需要数字的函数结果。
||
可以正常工作,因为这是字符串连接。
您需要以某种方式将您的 varchar2 转换为数字 (TO_NUMBER(f)
),或者编写您的 proc 以接受参数 f
作为数字而不是 varchar2。
【讨论】:
所以 Oracle 帮了我一个忙,它会检查绑定变量是否是正确的类型?对于f
,我的意图是生成一个类似begin :result := (a + b) / b; end;
的语句,但它失败了,因为:result
绑定到一个数字,而(a + b) / b
在绑定发生时是一个varchar2?
哦,您希望 f
成为 varchar2 "(a + b) / b"
吗?也就是说,f
是您要评估的字符串的文本?在这种情况下,绑定是不合适的,您应该使用字符串连接。或者看看这里有没有帮助:asktom.oracle.com/pls/asktom/…以上是关于为啥我不能在立即执行语句中使用绑定变量?的主要内容,如果未能解决你的问题,请参考以下文章