如何从单个 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