如何编写合并两个函数结果的PostgreSQL函数?
解决方案
方案一:使用PL/pgSQL实现条件判断(推荐)
你的两个辅助函数都是返回表类型的集合,而COALESCE仅支持标量值(单个值),所以无法直接用它合并集合结果。改用PL/pgSQL的条件逻辑可以完美实现需求:先检查子推荐是否有结果,有则返回,无则返回孙推荐结果。
CREATE OR REPLACE FUNCTION find_recommendation_in_group (group_id integer, title varchar) RETURNS TABLE (LIKE recommendations) AS $$ DECLARE child_row_count integer; BEGIN -- 检测子推荐是否存在结果 PERFORM * FROM find_child_recommendation_of_group(group_id, title); GET DIAGNOSTICS child_row_count = ROW_COUNT; IF child_row_count > 0 THEN -- 返回子推荐结果 RETURN QUERY SELECT * FROM find_child_recommendation_of_group(group_id, title); ELSE -- 无子推荐时返回孙推荐结果 RETURN QUERY SELECT * FROM find_grandchild_recommendation_of_group(group_id, title); END IF; END; $$ LANGUAGE plpgsql VOLATILE STRICT SECURITY DEFINER;
说明
PERFORM用于执行第一个函数但不返回结果,仅统计行数;GET DIAGNOSTICS获取执行后的行数,判断是否有有效结果;RETURN QUERY用于返回表类型结果集,匹配函数的返回要求。
方案二:纯SQL实现(无需PL/pgSQL)
如果偏好纯SQL写法,可以通过UNION ALL结合NOT EXISTS实现优先级逻辑:
CREATE OR REPLACE FUNCTION find_recommendation_in_group (group_id integer, title varchar) RETURNS TABLE (LIKE recommendations) AS $$ -- 优先返回子推荐结果 SELECT * FROM find_child_recommendation_of_group(group_id, title) UNION ALL -- 仅当子推荐无结果时,返回孙推荐结果 SELECT * FROM find_grandchild_recommendation_of_group(group_id, title) WHERE NOT EXISTS (SELECT 1 FROM find_child_recommendation_of_group(group_id, title)); $$ LANGUAGE sql VOLATILE STRICT SECURITY DEFINER;
说明
- 先执行子推荐查询,若有结果则直接返回;
- 若子推荐无结果,
NOT EXISTS条件成立,才会执行孙推荐查询; - 注意:如果子推荐查询耗时较高,此方案会执行两次子推荐查询(一次判断、一次返回),性能略逊于PL/pgSQL方案。
原方案报错原因
报错set-returning functions are not allowed in COALESCE的核心原因:
COALESCE是处理标量值的函数,参数必须是单个值(如整数、字符串);- 你的两个辅助函数都是返回表类型的集合(set-returning function),PostgreSQL不允许将集合函数作为
COALESCE的参数。
内容的提问来源于stack exchange,提问作者machineghost
相关产品推荐
相关产品推荐

