使用不确定数量的参数创建 Oracle function/macro
Create Oracle function/macro with an undeterminate number of arguments
是否可以创建 Oracle PL/SQL 函数或宏来帮助我生成一些代码?
例如
sumnull(a,b)
会return
coalesce(a, 0) + coalesce(b, 0) +
(case when coalesce(a, b) is not null then 0 else null end)
和
sumnull(a,b,c)
会return
coalesce(a, 0) + coalesce(b, 0) + coalesce(c, 0) +
(case when coalesce(a, b, c ) is not null then 0 else null end)
但是 sumnull 也可以接受 3 个以上的参数 (a,b,c,d,e.....)
在 C varargs
意义上,您不能有可变数量的参数(例如)。你可以重载一个函数,所以你有一个版本需要 2 个,另一个版本需要 3 个,等等,这将是一个难以维护的问题;或者有一长串值,它们都默认为零:
create or replace function sumnull (p_1 number default null, p_2 number default null,
p_3 number default null, p_4 number default null /*, etc. */)
return number as
begin
return coalesce(p_1, 0) + coalesce(p_2, 0)
+ coalesce(p_3, 0) + coalesce(p_4, 0) /* + etc. */;
end;
/
select sumnull() from dual;
SUMNULL()
----------
0
select sumnull(null) from dual;
SUMNULL(NULL)
-------------
0
select sumnull(1,null,7,9) from dual;
SUMNULL(1,NULL,7,9)
-------------------
17
但在某些时候你仍然需要设置一个上限,如果你尝试发送太多参数,它会出错,PLS-00306。重复这些子句有点乏味且可能容易出错。
另一种选择是传递一组值,例如:
create or replace function sumnull (p_values sys.odcinumberlist)
return number as
l_total number := 0;
begin
if p_values is null or p_values.count = 0 then
return l_total;
end if;
for i in 1..p_values.count loop
l_total := l_total + coalesce(p_values(i), 0);
end loop;
return l_total;
end;
/
然后你可以这样称呼它:
select sumnull(null) from dual;
SUMNULL(NULL)
-------------
0
select sumnull(sys.odcinumberlist()) from dual;
SUMNULL(SYS.ODCINUMBERLIST())
-----------------------------
0
select sumnull(sys.odcinumberlist(1,null,7,9)) from dual;
SUMNULL(SYS.ODCINUMBERLIST(1,NULL,7,9))
---------------------------------------
17
您也可以将列名作为较大查询的一部分传递;在此处对虚拟数据使用 CTE:
with t as (select 1 as a, null as b, 7 as c, 9 as d from dual)
select sumnull(sys.odcinumberlist(a, b, c, d)) from t;
SUMNULL(SYS.ODCINUMBERLIST(A,B,C,D))
------------------------------------
17
你可以在SQL级别定义你自己的集合类型当然,built-in sys.odcinumberlist
只是方便。
是否可以创建 Oracle PL/SQL 函数或宏来帮助我生成一些代码?
例如
sumnull(a,b)
会return
coalesce(a, 0) + coalesce(b, 0) +
(case when coalesce(a, b) is not null then 0 else null end)
和
sumnull(a,b,c)
会return
coalesce(a, 0) + coalesce(b, 0) + coalesce(c, 0) +
(case when coalesce(a, b, c ) is not null then 0 else null end)
但是 sumnull 也可以接受 3 个以上的参数 (a,b,c,d,e.....)
在 C varargs
意义上,您不能有可变数量的参数(例如)。你可以重载一个函数,所以你有一个版本需要 2 个,另一个版本需要 3 个,等等,这将是一个难以维护的问题;或者有一长串值,它们都默认为零:
create or replace function sumnull (p_1 number default null, p_2 number default null,
p_3 number default null, p_4 number default null /*, etc. */)
return number as
begin
return coalesce(p_1, 0) + coalesce(p_2, 0)
+ coalesce(p_3, 0) + coalesce(p_4, 0) /* + etc. */;
end;
/
select sumnull() from dual;
SUMNULL()
----------
0
select sumnull(null) from dual;
SUMNULL(NULL)
-------------
0
select sumnull(1,null,7,9) from dual;
SUMNULL(1,NULL,7,9)
-------------------
17
但在某些时候你仍然需要设置一个上限,如果你尝试发送太多参数,它会出错,PLS-00306。重复这些子句有点乏味且可能容易出错。
另一种选择是传递一组值,例如:
create or replace function sumnull (p_values sys.odcinumberlist)
return number as
l_total number := 0;
begin
if p_values is null or p_values.count = 0 then
return l_total;
end if;
for i in 1..p_values.count loop
l_total := l_total + coalesce(p_values(i), 0);
end loop;
return l_total;
end;
/
然后你可以这样称呼它:
select sumnull(null) from dual;
SUMNULL(NULL)
-------------
0
select sumnull(sys.odcinumberlist()) from dual;
SUMNULL(SYS.ODCINUMBERLIST())
-----------------------------
0
select sumnull(sys.odcinumberlist(1,null,7,9)) from dual;
SUMNULL(SYS.ODCINUMBERLIST(1,NULL,7,9))
---------------------------------------
17
您也可以将列名作为较大查询的一部分传递;在此处对虚拟数据使用 CTE:
with t as (select 1 as a, null as b, 7 as c, 9 as d from dual)
select sumnull(sys.odcinumberlist(a, b, c, d)) from t;
SUMNULL(SYS.ODCINUMBERLIST(A,B,C,D))
------------------------------------
17
你可以在SQL级别定义你自己的集合类型当然,built-in sys.odcinumberlist
只是方便。