从 Postgres 函数返回数据
Posted
技术标签:
【中文标题】从 Postgres 函数返回数据【英文标题】:Return data from Postgres functions 【发布时间】:2013-08-23 14:12:43 【问题描述】:我是 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,但结果相同。
当我查询它时,如果查询只返回一行,它工作正常。但是它不适用于多行。我也尝试过类似的方法,结果相同。大家能再帮忙吗?
也试过这个: 开始 sql_with_rows14.aid := (从 public.gc_alerts 中选择 a_id); sql_with_rows14.aname := (select a_name from public.gc_alerts);
RETURN NEXT;
END;
【问题讨论】:
【参考方案1】:我需要从 gc_vendors 表中返回不止一列
要返回具有多列(而不是一组行)的单行,您可以使用:
RETURNS row_type
.. 其中row_type
是一个预定义的复合类型(就像一个表名,它会自动用作这样的类型)。或者:
RETURNS record
结合OUT
参数。请注意,OUT
参数在正文中几乎无处不在,请避免使用naming conflicts。
使用第二个选项,您的函数可能如下所示:
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 语句。这只是一个展示案例。 The excellent manual has all the details.
你可以也用
RETURNS TABLE (...)
或者:
RETURNS SETOF row_type
这将允许您返回一组行(0、1 或许多)。但这不是你的问题。
要获取单个列而不是记录表示,请调用类似的函数:
SELECT <b>* FROM</b> sql_with_columns(...)
这里有很多关于 SO 的示例,请尝试使用 plpgsql 标记和一些关键词进行搜索。
在使用 plpgsql 的同时,还请阅读 how to return from a function in the manual. 章节
【讨论】:
我相信最后的“RETURN;”可以在“sql_with_columns”函数中省略。 @bma:我的评论说了很多,不是吗? Pavel(plpgsql 的主要贡献者)更喜欢明确的RETURN
,即使在示例中不需要也是如此。
确实如此。我不应该提到这一点,从你的“噪音”评论中可以明显看出它没有任何意义。对不起。【参考方案2】:
首先,考虑使用视图或简单查询。我想说,如果你可以用一个简单的查询来处理一些东西,你不应该为此创建函数。在您的情况下,您可以使用此查询
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 摆弄:)
【讨论】:
您好 Roman,您的回答很有帮助。我试图写一些类似的东西,但我在返回多行时遇到了问题。我有以下 @user2630270 关注什么?以上是关于从 Postgres 函数返回数据的主要内容,如果未能解决你的问题,请参考以下文章
从 Postgres 返回图像 url 到前端 - Node / React