泛型集返回函数

Posted

技术标签:

【中文标题】泛型集返回函数【英文标题】:Generic set returning function 【发布时间】:2014-11-21 17:21:05 【问题描述】:

我有一个 plpgsql 函数,它作为几个其他函数的包装器,所有这些函数都是设置返回不同数据类型的函数。通过这个函数,我试图得到一个通用的集合返回函数,它可以返回任何数据类型的集合。记录的数据类型由输入的表名和列名决定。

这里是sn-p的代码:

create function cs_get(tablename text, colname text) returns setof record as $$ 
declare
    type_name text;
    ctype text;
    loadfunc text;
    result record;
begin                                              
    select data_type into type_name from information_schema.columns where table_name = tablename and column_name = colname;
     if type_name is null then 
         raise exception 'Table % doesnot exist or does not have attribute % ',tablename,    colname;
    end if;

    ctype := cs_get_ctype(type_name);
    loadfunc := 'select * from cs_get_'||ctype||'('''||tablename||''','''||colname||''')';
    for result in execute loadfunc loop
        return next result;
    end loop;
    return;                                                      
end; $$ language plpgsql;

假设列是整数类型(对应的c类型是int64),loadfunc会是

select * from cs_get_int64(tablename, colname)

cs_get_int64 是一个定义在 C 库中的集合返回函数,它返回 int64 类型的值。

但是,这给出了一个错误提示

ERROR:  a column definition list is required for functions returning "record" at character 15

实现此目的的最简单方法是为每种数据类型返回一个setof text。但这当然不是一个干净的方法。我试过用

替换 loadFunc
select cs_get_int64::integer from cs_get_int64(tablename, colname)

这是使用记录所必需的。但是,这并没有帮助。

我现在的问题是: 是否可以创建这样一个通用的集合返回函数?如果是,如何?

【问题讨论】:

【参考方案1】:

答案是是的。但这不是微不足道的。

只要您返回匿名记录 (returns setof record),就需要列定义列表,返回的记录才能在 SQL 中使用。与错误消息中的内容差不多。

polymorphic types 有一个(有限的)方法:

CREATE OR REPLACE FUNCTION cs_get(_tbl_type anyelement, _colname text)
  RETURNS SETOF anyelement AS

...

这个相关答案的详细解释(上一章的高潮!):

Refactor a PL/pgSQL function to return the output of various SELECT queries

【讨论】:

以上是关于泛型集返回函数的主要内容,如果未能解决你的问题,请参考以下文章

返回类型为协议的泛型函数与参数和返回类型为协议的非泛型函数的区别

java 泛型函数需要返回Integer 我返回null 为啥报空指针异常

根据泛型参数返回函数签名

C#怎么定义泛型集合类型的函数,返回一个集合

具有高阶函数的泛型

使用条件返回类型实现泛型函数