从 postgres 返回多个结果集:引用、函数还是新特性?
Posted
技术标签:
【中文标题】从 postgres 返回多个结果集:引用、函数还是新特性?【英文标题】:Returning multiple result sets from postgres: refcursors, functions or new features? 【发布时间】:2018-11-22 19:33:01 【问题描述】:前提:
一个实体有很多孩子和孙子(在这个例子中,分别是要点、版本和文件)。当它(gist)被请求时,我们也想要它的子代(版本)和孙代(版本的文件)。在这里,我真的在努力尽可能多地使用 SQL,而不是将多个查询组合在一起并用脚本语言将它们组合在一起。可以做到吗?支持向 PostgresQL 数据库发送查询的工具是否支持返回的结果?
现有技术:
PostgreSQL function returning multiple result sets http://www.sqlines.com/postgresql/how-to/return_result_set_from_stored_procedure https://www.postgresql.org/docs/10/plpgsql-overview.html架构:
Schema (and SQL to insert mock data)
我通过存储函数的尝试(注意,我已简化为仅父/子返回集,暂时跳过孙子):
CREATE OR REPLACE FUNCTION get_gist_with_children(gist_ref refcursor,
version_ref refcursor, gist_id_in UUID)
RETURNS SETOF refcursor AS $$
BEGIN
OPEN gist_ref FOR SELECT * from gist where gist_id = gist_id_in;
RETURN NEXT gist_ref;
OPEN version_ref FOR SELECT * from version where gist_id = gist_id_in;
RETURN NEXT version_ref;
END;
$$ LANGUAGE plpgsql;
访问该函数的查询:
BEGIN;
SELECT get_gist_with_children('gist_ref', 'version_ref', <replace with known UUID of gist record>);
FETCH ALL IN "gist_ref";
FETCH ALL IN "version_ref";
COMMIT;
在 POSTICO 中返回 Postico 是一个 PostgresQL GUI,只返回两行中的引用符号字符串。
在 psql 中返回 psql 返回第一组结果然后...挂起?
注意:我可以成功查询该 gist_id 上的两个表和在单独查询中返回的记录。
Postgres 是否有新功能可以实现这一目标?有没有更好的方法来使用游标来做到这一点?工具(psql,Postico)不处理返回多个数据集的真正问题是什么?对通过脚本语言依赖组合之外的前进方式感到好奇。
【问题讨论】:
【参考方案1】:PostgreSQL 数据库引擎完全能够处理每个连接的多个打开的结果集,甚至每次调用。它可以使用多个“结果集”保留从单个调用返回的多个游标。
不要害怕使用它们。只需在您的过程中尝试多个 SELECT
s 并执行 SINGLE 调用。然后,很容易验证您是否可以从所有结果集中读取数据,甚至可以并行读取。
如果您在 mysql 上问过同样的问题,那么答案肯定会是“否”。 MySQL 的限制要多得多。但是对于 PostgreSQL,这是完全可能的。
【讨论】:
【参考方案2】:CREATE OR REPLACE FUNCTION public.TestReturnMultipleTales
(
param_coid integer,
ref1 refcursor,
ref2 refcursor
)
RETURNS SETOF refcursor
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
ROWS 1000
AS $BODY$
DECLARE
BEGIN
OPEN ref1 FOR SELECT * FROM dbo.tbl1 WHERE coid = param_coid;
RETURN NEXT ref1;
OPEN ref2 FOR SELECT * FROM dbo.tbl2 LIMIT 5;
RETURN NEXT ref2;
END;
$BODY$;
BEGIN;
SELECT football_players.show_cities_multiple(123456, 'Ref1', 'Ref2');
FETCH ALL IN "Ref1";
FETCH ALL IN "Ref2";
COMMIT;
【讨论】:
我会从一个单独的/远程客户端执行测试,但这是测试的要点。 +1以上是关于从 postgres 返回多个结果集:引用、函数还是新特性?的主要内容,如果未能解决你的问题,请参考以下文章