有什么方法可以确定pl_sql 函数中输入参数的数据类型,就像我们在 java 中有instanceof一样。我尝试过使用转储功能,但它只能在查询中使用。
问问题
1242 次
1 回答
0
从评论看来,您似乎想通过循环输入参数来构建动态查询字符串,大概是为了构建where
子句而无需手动输入。这似乎会使维护和理解变得更加困难,而没有太多好处。
但是,作为练习,您可以循环user_arguments
查看视图中的参数定义。问题是你不能在不命名的情况下获得实际的参数值,如果你这样做了,那么数据类型只有在你将值直接放入动态字符串时才重要(你不能在循环中真正做到这一点)而不是作为绑定变量,无论如何这都是一件坏事。如果你使用绑定变量,那么你不需要知道数据类型。
所以主要是为了我自己的娱乐,如果我有一个包含各种数据类型的表:
create table t42(col1 varchar2(10), col2 number, col3 date);
insert into t42 values ('data', 42, trunc(sysdate));
...以及参数名称与表列名称匹配的函数,然后您可以使用绑定变量构建动态字符串:
create function f42(col1 t42.col1%type, col2 t42.col2%type,
col3 t42.col3%type)
return varchar2 is
str varchar(4000);
result t42.col1%type;
have_where boolean := false;
begin
str := 'select col1 from t42';
for r in (
select argument_name, data_type
from user_arguments
where object_name = 'F42'
and position > 0 -- to account for return type
order by position
) loop
if not have_where then
have_where := true;
str := str || ' where ';
else
str := str || ' and ';
end if;
str := str || r.argument_name || ' = :' || r.argument_name;
end loop;
dbms_output.put_line(str);
execute immediate str into result using col1, col2, col3;
return result;
end;
/
然后我可以从 SQL*Plus 调用它:
SQL> var rc varchar2(10);
SQL> exec :rc := f42('data', 42, trunc(sysdate));
select col1 from t42 where COL1 = :COL1 and COL2 = :COL2 and COL3 = :COL3
PL/SQL procedure successfully completed.
SQL> print rc
RC
--------------------------------
data
显然是一个非常人为的例子,但它会随着更多参数进行扩展,只有using
子句需要将它们全部列出。我认为。这并不意味着我认为这是一个好主意 - 只是为了好玩......
如果需要,您可以通过检查值在循环中根据数据类型进行一些操作r.data_type
:
str := str || r.argument_name || ' = ';
if r.data_type = 'DATE' then
str := str || 'trunc(:' || r.argument_name || ')';
else
str := str || ':' || r.argument_name;
end if;
...然后您可以调用它而无需调用中trunc
的值:
SQL> exec :rc := f42('data', 42, sysdate);
select col1 from t42 where COL1 = :COL1 and COL2 = :COL2 and COL3 = trunc(:COL3)
PL/SQL procedure successfully completed.
SQL> print rc
RC
--------------------------------
data
...但除此之外,您不需要知道动态字符串中每一列的类型,因为无论如何绑定都会处理这个问题。
于 2013-04-10T11:42:56.220 回答