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