我在后端使用 postgresql 8.4
我有一个 postgres 函数说 A(),它可以返回一组记录(3 列),如下所示:
<A_id>::int,<A_ts_1>::timestamp,<A_ts_2>::timestamp
函数 A 定义如下(例如):
CREATE OR REPLACE FUNCTION A()
RETURNS SETOF record AS
$$
DECLARE
BEGIN
RETURN QUERY SELECT DISTINCT ON (A.id) A.id, A.ts_1, A.ts_2 FROM tablea;
END;
$$ LANGUAGE plpgsql;
SQL
函数 A 已在另一个函数 B 中调用。在函数 B 中,我需要一个变量来保存从 A() 返回的内容,然后执行一些查询,例如:
<variable> = select * from A();
a_id_array = ARRAY(select A_id from <variable>);
a_filtered_array = ARRAY(select A_id from <variable> where A_ts_1 ><a_timestamp> and A_ts_2 < <a_timestamp>);
所以我的问题是我应该定义什么变量来保存从 A() 返回的记录集。
我尝试了临时表,它真的不适合多会话环境,它会阻止数据插入。 PostgreSQL 创建临时表可以阻止数据插入吗?
我检查了文档的视图似乎不符合我的要求,但是我可能错了,所以如果你们中的任何人可以给我一个关于在这种情况下如何使用视图和使用视图的想法,也会阻止数据插入?
谢谢大家!
附言 我认为最糟糕的情况是在函数 B() 中,我调用函数 A() 两次,例如:
a_id_array = ARRAY(select A_id from A());
a_filtered_array = ARRAY(select A_id from A() where A_ts_1 ><a_timestamp> and A_ts_2 < <a_timestamp>);
然后我的问题会略有改变,我可以只使用一个函数调用 A() 来实现这种情况吗?
PostgreSQL还没有(从postgres 10开始)有由元组存储支持的表值变量。因此,您最好的选择是:
-
返回一个
REFCURSOR
并从另一个函数中使用它。使用起来可能很笨拙,因为您无法在子查询中轻松重用或FETCH
结果集。生成游标结果集并不总是那么容易,具体取决于您创建结果的方式。 -
使用具有生成名称的临时表,以免它们发生冲突。这里涉及很多动态SQL(
EXECUTE format(...)
),但它可以工作。 -
避免尝试在函数之间传递结果集
经过研究,找到了一种使用临时表替换的方法,并查询返回的记录集,该记录集使用WITH查询。
SELECT c.r_ids, c.a_r_ids into a_id_array, a_filtered_array FROM(
WITH returned_r AS (SELECT * FROM a())
SELECT * from (
SELECT ARRAY( SELECT A_id from returned_r ) as r_ids ) as a
CROSS JOIN (
SELECT ARRAY(SELECT A_id FROM returned_r WHERE A_ts_1 is NOT NULL AND A_ts_2 IS NULL) as a_r_ids
) as b
) as c;