如何在 PostgreSQL 中的函数内返回动态 SELECT 的结果?

问题描述

非常相似的question here,但与此不完全相同。

我有一个函数,它使用 IF 语句来确定要返回的 SELECT 查询类型。

当我永远不知道 CREATE FUNCTION 查询可能返回的确切列时,我如何声明 SELECT 语句应返回的内容?也就是说,我无法使用列列表设置 RETURNS TABLE 声明,因为我不知道哪些列可能会返回。我所知道的是,我肯定希望返回一个结果表。

这是我的函数(未完成,伪):

CREATE OR REPLACE FUNCTION functiona(_url character varying DEFAULT NULL) 
RETURNS -- what type? if TABLE how do I kNow what columns to specify
    LANGUAGE plpgsql
AS
$$
DECLARE
    _urltypeid int;
BEGIN
    IF _url IS NOT NULL
    THEN
        _urltypeid := reference.urltype(_url);
        IF _urltypeid = 1
        THEN
            RETURN QUERY
                SELECT location,auxiliary,response FROM tablea -- unique columns from one table
        END IF;
    IF _urltypeid = 2
        THEN
            RETURN QUERY
                SELECT ip,location,host,authority FROM tableb -- unique columns from another table
        END IF;
    END IF;
END;
$$;

我来自 MS sql Server 背景,我不必在 CREATE FUNCTION 语句中指定我要返回的内容,因此这对我来说非常混乱。

解决方法

不是答案,而是使用一个简单的例子解释为什么@JonathanJacobson 的答案不起作用:

\d animals
                      Table "public.animals"
 Column |          Type          | Collation | Nullable | Default 
--------+------------------------+-----------+----------+---------
 id     | integer                |           | not null | 
 cond   | character varying(200) |           | not null | 
 animal | character varying(200) |           | not null | 

CREATE OR REPLACE FUNCTION public.animal(a_type character varying)
 RETURNS record
 LANGUAGE plpgsql
AS $function$
BEGIN
    SELECT row(id,cond,animal) FROM animals where animal = a_type;
END;
$function$

select * from animal('cat');
ERROR:  a column definition list is required for functions returning "record"
LINE 1: select * from animal('cat');

CREATE OR REPLACE FUNCTION public.animal(a_type character varying)
 RETURNS SETOF record
 LANGUAGE plpgsql
AS $function$
BEGIN
    RETURN QUERY
    SELECT id,animal FROM animals where animal = a_type;
END;
$function$
;

 select * from animal('cat') as t(i integer,c varchar,a varchar);
 i |  c   |  a  
---+------+-----
 1 | fat  | cat
 2 | slim | cat
 6 | big  | cat

为了使用返回 recordsetof record 的函数的输出,您需要在运行函数时声明输出字段和类型。

,

您可以使用 record 类型。未测试。

CREATE OR REPLACE FUNCTION functiona(_url character varying DEFAULT NULL)
RETURNS record
    LANGUAGE plpgsql
AS
$$
DECLARE
    _broadcasttypeid int;
BEGIN
    IF _url IS NOT NULL
    THEN
        _urltypeid := reference.urltype(_url);
        IF _urltypeid = 1
        THEN
            RETURN
                (SELECT row(location,auxiliary,response) FROM tablea);
        END IF;
    IF _urltypeid = 2
        THEN
            RETURN
                (SELECT row(ip,location,host,authority) FROM tableb);
        END IF;
    END IF;
END;
$$;

其他复合类型,例如 jsonbhstore 也是一种解决方案。