从 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 数据库引擎完全能够处理每个连接的多个打开的结果集,甚至每次调用。它可以使用多个“结果集”保留从单个调用返回的多个游标。

不要害怕使用它们。只需在您的过程中尝试多个 SELECTs 并执行 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 返回多个结果集:引用、函数还是新特性?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Postgres 中使用 Plpython3 返回结果集

如何在 Postgres 函数中检索多个结果行?

POSTGRES:选择从函数返回的引用的查询

Greenplum/Postgres 8 函数动态结果集?

Postgres:从存储函数返回结果或错误

如何从postgres函数返回两个SELECT语句的结果?