创建具有不确定数量参数的 Oracle 函数/宏

Posted

技术标签:

【中文标题】创建具有不确定数量参数的 Oracle 函数/宏【英文标题】:Create Oracle function/macro with an undeterminate number of arguments 【发布时间】:2015-01-07 15:45:32 【问题描述】:

是否可以创建一个 Oracle PL/SQL 函数或宏来帮助我生成一些代码?

例如

sumnull(a,b) 

会回来

coalesce(a, 0) + coalesce(b, 0) +
        (case when coalesce(a, b) is not null then 0 else null end)

sumnull(a,b,c)

会返回

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.....)

【问题讨论】:

【参考方案1】:

在 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 只是方便。

【讨论】:

谢谢!所以出于好奇,Coalesce() 如何获得不确定数量的参数? 我可以用列名代替数字吗? 嗯,好问题;我想它是在较低级别实现的,在 C 或其他核心数据库代码的一部分中,而不是在 PL/SQL 中。虽然这增加了我想使用 Java 函数的可能性。我认为 coalesce 仍然限制为 1000 个参数,这是值列表的正常限制。 @Stephane - 是的,我在答案中添加了一个示例。

以上是关于创建具有不确定数量参数的 Oracle 函数/宏的主要内容,如果未能解决你的问题,请参考以下文章

具有在编译时确定的参数数量的 Lambda 函数

在 Postgresql 中创建一个具有多列作为参数的函数

php函数调用参数的问题,主要是参数数量不确定。

使用 3 个值中确定的参数值创建特定数量的代理

创建具有动态参数数量的 MySQL 存储函数

创建具有可变数量参数的 CLR UDF