我正在尝试将这种格式的嵌套数据从 PostgreSQL 返回到 PHP 关联数组中。
[
'person_id': 1,
'name': 'My Name',
'roles': [
[ 'role_id': 1, 'role_name': 'Name' ],
[ 'role_id': 2, 'role_name': 'Another role name' ]
]
]
似乎可以使用复合类型。这个答案描述了如何从函数返回复合类型,但它不处理复合类型的数组。我在使用数组时遇到了一些问题。
这是我的表格和类型:
CREATE TEMP TABLE people (person_id integer, name text);
INSERT INTO "people" ("person_id", "name") VALUES
(1, 'name!');
CREATE TEMP TABLE roles (role_id integer, person_id integer, role_name text);
INSERT INTO "roles" ("role_id", "person_id", "role_name") VALUES
(1, 1, 'role name!'),
(2, 1, 'another role');
CREATE TYPE role AS (
"role_name" text
);
CREATE TYPE person AS (
"person_id" int,
"name" text,
"roles" role[]
);
我的get_people()
函数解析良好,但存在运行时错误。现在我收到错误:array value must start with "{" or dimension information
CREATE OR REPLACE FUNCTION get_people()
RETURNS person[] AS $$
DECLARE myroles role[];
DECLARE myperson people%ROWTYPE;
DECLARE result person[];
BEGIN
FOR myperson IN
SELECT *
FROM "people"
LOOP
SELECT "role_name" INTO myroles
FROM "roles"
WHERE "person_id" = myperson.person_id;
result := array_append(
result,
(myperson.person_id, myperson.name, myroles::role[])::person
);
END LOOP;
RETURN result;
END; $$ LANGUAGE plpgsql;
更新以回答 Erwin Brandstetter 在回答末尾的问题:
是的,我可以返回一个复合类型的 SETOF。我发现 SET 比数组更容易处理,因为 SELECT 查询返回 SET。我宁愿返回嵌套数组的原因是因为我认为将嵌套数据表示为一组行有点尴尬。这是一个例子:
person_id | person_name | role_name | role_id
-----------+-------------+-----------+-----------
1 | Dilby | Some role | 1978
1 | Dilby | Role 2 | 2
2 | Dobie | NULL | NULL
在此示例中,人员 1 有 2 个角色,而人员 2 没有。我正在为我的另一个 PL/pgSQL 函数使用这样的结构。我编写了一个脆弱的 PHP 函数,可以将这样的记录集转换为嵌套数组。
这种表示工作正常,但我担心向这个结构添加更多的嵌套字段。如果每个人也有一组工作怎么办?状态?等我的转换功能将不得不变得更加复杂。数据的表示也会很复杂。如果一个人有n 个角色、m个工作和o个状态,则该人填充max(n, m, o)
行,其中person_id
,person_name
,以及它们在额外行中无用地复制的任何其他数据。我一点也不担心性能,但我想以最简单的方式做到这一点。当然..也许这是最简单的方法!
我希望这有助于说明为什么我宁愿直接处理 PostgreSQL 中的嵌套数组。当然,我很想听听您的任何建议。
对于使用 PHP 处理 PostgreSQL 复合类型的任何人,我发现这个库对于在 PHP 中解析 PostgreSQL 的 array_agg() 输出非常有用:https ://github.com/nehxby/db_type 。此外,这个项目看起来很有趣:https ://github.com/chanmix51/Pomm