如何从单个 PL/pgSQL 函数中 return 不同格式的记录?
How to return different format of records from a single PL/pgSQL function?
我是一名前端开发人员,但我开始编写后端的东西。我花了相当多的时间试图弄清楚如何解决这个问题。我真的需要一些帮助。
下面是两个table的简化定义和关系:
Relationship between tables
CREATE TABLE IF NOT EXISTS items (
item_id uuid NOT NULL DEFAULT gen_random_uuid() ,
parent_id uuid DEFAULT NULL ,
parent_table parent_tables NOT NULL
);
CREATE TABLE IF NOT EXISTS collections (
collection_id uuid NOT NULL DEFAULT gen_random_uuid() ,
parent_id uuid DEFAULT NULL
);
我们的产品是在线文档协作工具,页面可以嵌套。
我有一段 PostgreSQL 代码,用于获取给定 item_ids 的所有祖先记录。
WITH RECURSIVE ancestors AS (
SELECT *
FROM items
WHERE item_id in ( ${itemIds} )
UNION
SELECT i.*
FROM items i
INNER JOIN ancestors a ON a.parent_id = i.item_id
)
SELECT * FROM ancestors
它适用于嵌套常规页面,但如果我要支持嵌套集合页面,这意味着某些项目的 parent_id 可能引用“集合”table 的 collection_id,此代码将不再有效。根据我有限的经验,我认为纯 SQL 代码不能解决它。我认为编写一个 PL/pgSQL 函数可能是一个解决方案,但我需要将所有祖先记录获取给定 itemIds
,这意味着 return 混合项目和集合记录。
那么如何从单个 PL/pgSQL 函数 return 不同格式的记录?我做了一些研究,但没有找到任何例子。
您可以通过 返回超集 作为行来使其工作:由项目 和 集合组成。对于每个结果行,两者之一将是 NULL
。
WITH RECURSIVE ancestors AS (
SELECT 0 AS lvl, i.parent_id, i.parent_table, i AS _item, NULL::collections AS _coll
FROM items i
WHERE item_id IN ( ${itemIds} )
UNION ALL -- !
SELECT lvl + 1, COALESCE(i.parent_id, c.parent_id), COALESCE(i.parent_table, 'i'), i, c
FROM ancestors a
LEFT JOIN items i ON a.parent_table = 'i' AND i.item_id = a.parent_id
LEFT JOIN collections c ON a.parent_table = 'c' AND c.collection_id = a.parent_id
WHERE a.parent_id IS NOT NULL
)
SELECT lvl, _item, _coll
FROM ancestors
-- ORDER BY ?
db<>fiddle here
UNION ALL
,不是UNION
。
假设一个集合的父级始终是一个项目,而一个项目可以是任何一种方式。
我们需要 LEFT JOIN
在两个潜在的父表上才能留在比赛中。
我添加了一个可选的 lvl
来跟踪层次结构级别。
关于分解行类型:
- Combine postgres function with query
- Record returned from function has columns concatenated
我是一名前端开发人员,但我开始编写后端的东西。我花了相当多的时间试图弄清楚如何解决这个问题。我真的需要一些帮助。
下面是两个table的简化定义和关系:
Relationship between tables
CREATE TABLE IF NOT EXISTS items (
item_id uuid NOT NULL DEFAULT gen_random_uuid() ,
parent_id uuid DEFAULT NULL ,
parent_table parent_tables NOT NULL
);
CREATE TABLE IF NOT EXISTS collections (
collection_id uuid NOT NULL DEFAULT gen_random_uuid() ,
parent_id uuid DEFAULT NULL
);
我们的产品是在线文档协作工具,页面可以嵌套。
我有一段 PostgreSQL 代码,用于获取给定 item_ids 的所有祖先记录。
WITH RECURSIVE ancestors AS (
SELECT *
FROM items
WHERE item_id in ( ${itemIds} )
UNION
SELECT i.*
FROM items i
INNER JOIN ancestors a ON a.parent_id = i.item_id
)
SELECT * FROM ancestors
它适用于嵌套常规页面,但如果我要支持嵌套集合页面,这意味着某些项目的 parent_id 可能引用“集合”table 的 collection_id,此代码将不再有效。根据我有限的经验,我认为纯 SQL 代码不能解决它。我认为编写一个 PL/pgSQL 函数可能是一个解决方案,但我需要将所有祖先记录获取给定 itemIds
,这意味着 return 混合项目和集合记录。
那么如何从单个 PL/pgSQL 函数 return 不同格式的记录?我做了一些研究,但没有找到任何例子。
您可以通过 返回超集 作为行来使其工作:由项目 和 集合组成。对于每个结果行,两者之一将是 NULL
。
WITH RECURSIVE ancestors AS (
SELECT 0 AS lvl, i.parent_id, i.parent_table, i AS _item, NULL::collections AS _coll
FROM items i
WHERE item_id IN ( ${itemIds} )
UNION ALL -- !
SELECT lvl + 1, COALESCE(i.parent_id, c.parent_id), COALESCE(i.parent_table, 'i'), i, c
FROM ancestors a
LEFT JOIN items i ON a.parent_table = 'i' AND i.item_id = a.parent_id
LEFT JOIN collections c ON a.parent_table = 'c' AND c.collection_id = a.parent_id
WHERE a.parent_id IS NOT NULL
)
SELECT lvl, _item, _coll
FROM ancestors
-- ORDER BY ?
db<>fiddle here
UNION ALL
,不是UNION
。
假设一个集合的父级始终是一个项目,而一个项目可以是任何一种方式。
我们需要 LEFT JOIN
在两个潜在的父表上才能留在比赛中。
我添加了一个可选的 lvl
来跟踪层次结构级别。
关于分解行类型:
- Combine postgres function with query
- Record returned from function has columns concatenated