PostgreSQL如何从变量中查询数据?plpgsql函数查询record变量报错如何解决
问题原因
- 你声明的
all_user_average_scores是record类型,该类型仅支持存储单行数据,而你执行的GROUP BY user_uuid查询会返回多行结果,本身赋值逻辑就存在隐含错误。 - 核心报错原因:PL/pgSQL的普通变量(包括record、数值、字符串等类型)不能直接作为关系表放在
FROM子句中查询,数据库会将其识别为普通数据表去系统表中查找,自然会报不存在该关系的错误。 - 额外的语法问题:代码中使用的
max_raw、min_raw、final_result三个变量均未提前声明,即便解决当前报错,后续也会触发变量未定义的错误。
解决方案
场景1:不需要保留所有用户的平均得分,仅需要最大、最小平均值
直接用子查询一步计算出结果,不需要中间变量,性能最高,代码示例:
CREATE OR REPLACE FUNCTION public.my_func() RETURNS NUMERIC LANGUAGE plpgsql AS $function$ DECLARE max_avg numeric; min_avg numeric; final_result numeric; -- 补充声明返回值变量 BEGIN -- 直接计算所有用户平均得分的最大值和最小值 SELECT max(avg_score), min(avg_score) INTO max_avg, min_avg FROM ( SELECT AVG(score) as avg_score FROM user_scores GROUP BY user_uuid ) t; -- 你的后续逻辑 -- final_result := 你的计算逻辑 RETURN final_result; END; $function$;
场景2:后续逻辑需要用到所有用户的平均得分
你可以使用临时表存储中间结果,临时表可以正常在FROM子句中查询,函数执行结束后临时表会自动清理,代码示例:
CREATE OR REPLACE FUNCTION public.my_func() RETURNS NUMERIC LANGUAGE plpgsql AS $function$ DECLARE max_avg numeric; min_avg numeric; final_result numeric; BEGIN -- 创建临时表存储所有用户的平均得分 CREATE TEMP TABLE IF NOT EXISTS all_user_average_scores ( user_uuid uuid, avg_score numeric ) ON COMMIT DROP; -- 写入平均得分数据 INSERT INTO all_user_average_scores SELECT user_uuid, AVG(score) as avg_score FROM user_scores GROUP BY user_uuid; -- 从临时表查询最大最小值 SELECT max(avg_score) INTO max_avg FROM all_user_average_scores; SELECT min(avg_score) INTO min_avg FROM all_user_average_scores; -- 你的后续逻辑 -- final_result := 你的计算逻辑 RETURN final_result; END; $function$;
内容的提问来源于stack exchange,提问作者shawn
相关产品推荐
相关产品推荐

