为什么我不能在execute immediate语句中使用绑定变量?

时间:2011-08-02 05:23:17

标签: oracle plsql oracle11g execute-immediate

当我为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;

2 个答案:

答案 0 :(得分:2)

绑定变量用于绑定变量,而不是用于绑定代码段。这个想法是Oracle可以编译和缓存查询或代码块,并使用不同的参数执行几次。

但是,您尝试使用参数绑定来替换计算公式。它会阻止编译和缓存代码块,因此不受支持。

此外,它不能用当前语法表达。如果Oracle看到tmp := :f,则认为您只想将参数f分配给变量tmp。它不期望必须评估函数。

请继续使用工作解决方案。它毕竟有用。

答案 1 :(得分:1)

发生错误是因为您将f声明为varchar2,但您已在注释掉的部分中写了以下内容:

tmp number; begin tmp := :f ...

您尝试将“character”值分配给需要数字的变量。您还尝试将f分配给函数结果,该结果再次需要一个数字。

使用||可以正常工作,因为这是字符串连接。

您需要将varchar2转换为数字(TO_NUMBER(f)),或者编写您的proc以接受参数f作为数字而不是varchar2。