0

我是 PostgreSQL 的新手,在让它做我想做的事情时遇到了一些问题。

我需要构建一个可以接受多个变量的函数,在内部执行多个查询,然后返回一个由几行和几列组成的数据集。我已经构建了几个测试函数来更好地掌握 Postgres 的功能,这里是一个:

 CREATE OR REPLACE FUNCTION sql_with_rows11(id integer) RETURNS character varying AS $BODY$
 declare vid integer;
 declare vendor character varying;
 BEGIN
 vid := (select v_id from public.gc_alerts where a_id = id);
 vendor := (select v_name from public.gc_vendors where v_id = vid);

   RETURN vendor;
   END;
 $BODY$
   LANGUAGE plpgsql VOLATILE
   COST 100;
 ALTER FUNCTION sql_with_rows11(integer)
   OWNER TO postgres;

我知道我可以将其组合成一个查询,但这更像是一种练习。这工作正常,我得到了供应商名称。但是,现在我需要从表中返回不止一列gc_vendors

最后,我将需要构建一个函数,该函数将根据子查询从多个表中返回列。我已经研究过创建一个结果集函数,但我相信它一次只返回一行。我还研究了返回 setof 类型,但这似乎仅限于存在的表。

- - - - - - - 编辑

嘿伙计们,谢谢你的帮助。我将功能更改为以下内容:

 CREATE OR REPLACE FUNCTION sql_with_rows14(IN v_uid character varying, IN lid           integer) 
 RETURNS table (aid int, aname character varying) AS $BODY$
 declare aid integer;
 declare aname character varying;
 BEGIN
 sql_with_rows14.aid := (select a_id from public.gc_alerts where v_id =           sql_with_rows14.v_uid);
 sql_with_rows14.aname := (select a_name from public.gc_alerts where a_id =      sql_with_rows14.aid);

   RETURN;
   END;
 $BODY$
   LANGUAGE plpgsql VOLATILE

我也尝试使用 RETURN NEXT,但结果相同。

当我查询它时,如果查询只返回一行,它工作正常。但是它不适用于多行。我也尝试过类似的方法,结果相同。大家能再帮忙吗?

也试过这个: BEGIN sql_with_rows14.aid := (select a_id from public.gc_alerts); sql_with_rows14.aname := (从 public.gc_alerts 中选择 a_name);

   RETURN NEXT;
   END;
4

2 回答 2

2

我需要从 gc_vendors 表中返回多于一列

要返回具有多列的单行(而不是一组行),您可以使用:

RETURNS row_type

.. whererow_type是一个预定义的复合类型(就像一个表名,它会自动充当这样的角色)。或者:

RETURNS record

结合OUT参数。请注意,OUT参数在正文中几乎无处不在,并避免命名冲突
使用第二个选项,您的函数可能如下所示:

CREATE OR REPLACE FUNCTION sql_with_columns(
      IN  _id integer   -- the IN key word is just noise
    , OUT vid integer
    , OUT vendor text
    ) RETURNS record AS
$func$
BEGIN

SELECT INTO vid  v_id
FROM   public.gc_alerts
WHERE  a_id = id;

SELECT INTO vendor  v_name
FROM   public.gc_vendors
WHERE  v_id = vid;

RETURN;     -- just noise, since OUT parameters are returned automatically

END
$func$ LANGUAGE plpgsql

正如您所提到的,您应该将两个查询合并为一个,或者甚至使用普通的 SQL 语句。这只是一个展示案例。优秀的手册包含所有细节。

可以使用

RETURNS TABLE (...)

或者:

RETURNS SETOF row_type

这将允许您返回一组行(0、1 或许多)。但这不是你的问题。

获取单个列而不是记录表示,请调用类似的函数:

SELECT * FROM sql_with_columns(...)

这里有很多关于 SO 的示例,请尝试使用标记和一些关键词进行搜索。

在使用 plpgsql 时,还请阅读手册中有关如何从函数返回的章节。

于 2013-08-23T15:18:55.500 回答
1

首先,考虑使用视图或简单查询。我想说,如果你可以用一个简单的查询来处理一些东西,你不应该为此创建函数。在您的情况下,您可以使用此查询

select
    v.v_name, v.* -- or any other columns from gc_alerts or gc_vendors
from public.gc_alerts as a
    inner join public.gc_vendors as v on v.v_id = a.vid
where a.a_id = <your id here>

如果你想让你的函数返回行,你可以像这样声明它

CREATE OR REPLACE FUNCTION sql_with_rows11(id integer)
RETURNS table(vendor text, v_id int)
as
$$
    select
        v.v_name, v.v_id
    from public.gc_alerts as a
        inner join public.gc_vendors as v on v.v_id = a.vid
    where a.a_id = id
$$ language SQL;

或 plpgsql 函数:

CREATE OR REPLACE FUNCTION sql_with_rows11(id integer)
RETURNS table(vendor text, vid int)
AS
$$
    declare vid integer;
    declare vendor character varying;
BEGIN
    sql_with_rows11.vid := 1; -- prefix with function name because otherwise it would be declared variables
    sql_with_rows11.vendor := 4;
    return next; 

    sql_with_rows11.vid := 5;
    sql_with_rows11.vendor := 8;
    return next;
END;
$$ LANGUAGE plpgsql;

sql fiddle demo摆弄:)

于 2013-08-23T14:20:41.197 回答