Postgresql - 从 plpgsql 函数返回记录 []
Posted
技术标签:
【中文标题】Postgresql - 从 plpgsql 函数返回记录 []【英文标题】:Postgresql - return a record[] from a plpgsql function 【发布时间】:2021-11-22 00:09:29 【问题描述】:我有一个employer
和一个employee
表。我有一个连接它们的连接表。
CREATE TABLE employer (id int primary key, name text);
CREATE TABLE employee (id int primary key, name text);
CREATE TABLE employer_employee_join(
employer_id int REFERENCES employer(id),
employee_id int REFERENCES employee(id)
);
INSERT INTO employer (id, name) VALUES (1, 'the boss');
INSERT INTO employee (id, name) VALUES (1, 'employee1');
INSERT INTO employee (id, name) VALUES (2, 'employee2');
INSERT INTO employer_employee_join (employer_id, employee_id) VALUES(1, 1);
INSERT INTO employer_employee_join (employer_id, employee_id) VALUES(1, 2);
我的 sql 查询返回 employer
并聚合 employee
返回一个记录数组 (record[]
)。
SELECT
employer.id, employer.name, array_agg((employee.id, employee.name))
FROM employer
LEFT JOIN employer_employee_join
ON employer_employee_join.employer_id = employer.id
LEFT JOIN employee
ON employee.id = employer_employee_join.employee_id
GROUP BY employer.id;
这很好用。
但是当我把它放在一个 PL/PGSQL 函数中时它失败了:
CREATE OR REPLACE FUNCTION _test()
RETURNS table(id integer, name text, agg record[])
LANGUAGE 'plpgsql'
AS $BODY$
begin
SELECT
employer.id, employer.name, array_agg((employee.id, employee.name))
FROM employer
LEFT JOIN employer_employee_join
ON employer_employee_join.employer_id = employer.id
LEFT JOIN employee
ON employee.id = employer_employee_join.employee_id
GROUP BY employer.id;
end;
$BODY$
错误是
ERROR: PL/pgSQL functions cannot accept type record[]
SQL state: 0A000
如何让 plpgsql 函数返回记录数组?
(我真的不想使用json_agg()
,因为系统中的另一层不在postgresql和我的控制范围内)
【问题讨论】:
您真正想要的是(int, text)
tuple,而不是任意的record
。事实上你已经有了那个类型的名字,所以你可以写employee[]
。
"我的 sql 查询返回雇主并汇总雇员" - 你为什么要这样做? “我真的不想使用json_agg()
,因为我的系统中有另一层” - 什么是“另一层”,它如何处理 postgres 记录数组,而不是结构化和简单可解析的 json ?
谢谢,Bergi。 employee[]
是我要找的。但是当我只想返回一个表的一个子部分时,我可以返回一个元组数组吗? (另一层在 postgresql 之外。)
如果您只需要选择的列,您可以为此定义一个自定义复合类型。请参阅我链接的文档。
啊,我终于到了。感谢您的帮助。
【参考方案1】:
感谢@Bergi。这是我需要的composite type。
create type employee_agg as (id int, name text);
CREATE OR REPLACE FUNCTION _test()
RETURNS table(id integer, name text, agg employee_agg[])
LANGUAGE plpgsql
AS $BODY$
begin
return query
SELECT
employer.id,
employer.name,
array_agg(row(employee.id, employee.name)::employee_agg)
FROM employer
LEFT JOIN employer_employee_join
ON employer_employee_join.employer_id = employer.id
LEFT JOIN employee
ON employee.id = employer_employee_join.employee_id
GROUP BY employer.id;
end;
$BODY$;
【讨论】:
别那样做……用 SQL 吧……【参考方案2】:使用视图
就这样吧……
CREATE VIEW _test
AS
SELECT
employer.id,
employer.name,
array_agg(row(employee.id, employee.name)::employee_agg)
FROM employer
LEFT JOIN employer_employee_join
ON employer_employee_join.employer_id = employer.id
LEFT JOIN employee
ON employee.id = employer_employee_join.employee_id
GROUP BY employer.id;
你的函数没有参数,它只是一个查询。这是一个更好的主意。
或者,您可以使用SQL
函数(但视图更好)。
【讨论】:
悲哀一定是个函数。 @mmm111mmm 然后使用 SQL。它的工作原理相同,但速度会更快。以上是关于Postgresql - 从 plpgsql 函数返回记录 []的主要内容,如果未能解决你的问题,请参考以下文章
尝试使用 RETURNING 和更新/插入从 plpgsql 函数返回时出错
PostgreSQL - 继续 unique_violation (plpgsql)