为啥我不能在立即执行语句中使用绑定变量?

Posted

技术标签:

【中文标题】为啥我不能在立即执行语句中使用绑定变量?【英文标题】:Why I can't use a bind variable in an execute immediate statement?为什么我不能在立即执行语句中使用绑定变量? 【发布时间】:2011-08-02 05:23:16 【问题描述】:

当我为execute immediate 构建动态 SQL 语句时,我想使用绑定变量而不是字符串连接。

在下面的示例中,我可以为abret 使用绑定变量,但是当我尝试为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/…

以上是关于为啥我不能在立即执行语句中使用绑定变量?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这里使用立即执行?

如何在立即执行中处理管道和绑定变量

立即执行无法将结果绑定到变量中

sql select语句作为动态plsql块的绑定变量

我不能在 datagrip 中使用绑定变量

Oracle绑定变量