我需要提供一些存储过程,这些过程返回在数据库中选择的值上运行的聚合函数的结果,即平均值,总和,最小值,最大值等。值的选择总是在类似的方式。
我的第一个天真实现包括每个聚合函数类型的一个存储过程,例如: get_avg(...),get_sum(...)。这些功能显然共享了很多重复的代码。我想知道是否有办法将聚合类型移动到参数左右,然后只使用一个存储过程,例如get_aggregate(aggr_type,...)
就pl / pgsql实现而言,我能想到的唯一方法是选择应该进入聚合的值,然后在aggr_type == ... / else子句中使用它们。是聚合类型。但这不是很灵活,只要需要支持新的聚合类型,就需要更改代码。
有没有办法在pl / pgsql中参数化函数的名称? 你能想到一种我看不到的方法吗?
答案 0 :(得分:1)
从技术上讲,您可以在plpgsql函数中使用execute
语句:
return query
execute $x$
select id, $x$ || quote_ident(agg_func) || $x$(col)::numeric as agg
from bar
$x$;
(参见下面的正确例子)。问题是,这将意味着在每次调用时解析/规划您的查询。
有时,更好的选择是创建一个创建各种所需功能的功能。像这样:
create or replace function generate_agg_functions(_table regclass) returns void as $$
declare
_agg_type text[] = '{sum, avg}';
_ret_type regtype[] = '{numeric, numeric}';
rec record;
begin
for rec in select _agg_type[i] as agg_type, _ret_type[i] as ret_type
from generate_subscripts(_agg_type, 1) i
loop
execute $x$
create or replace function $x$ || quote_ident(_table || '_' || rec.agg_func) || $x$()
returns table (id int, $x$ || quote_ident(rec.agg_type) || ' ' || ret_type || $x$)
$def$
begin
return query
select id,
$x$ || quote_ident(rec.agg_type) || $x$(col)::$x$ || rec.ret_type || $x$
as $x$ || quote_ident(rec.agg_type) || $x$
from $x$ || _table || $x$;
end;
$def$ language plpgsql stable;
$x$;
end loop;
end;
$$ language plpgsql;
编写起来有点棘手,但最终不会在不影响单个聚合的性能的情况下复制代码。