PostgreSQL存储过程统计买家消费额报42601无结果目标错误如何修复
问题原因分析
你遇到的报错是PostgreSQL的PL/pgSQL语法和MySQL存储过程语法的差异导致的,具体问题有三个:
- PL/pgSQL中执行SELECT查询如果目的是给变量赋值,必须加
INTO子句指定接收结果的变量,你写的select sum (price) as temp_sum...没有指定赋值目标,因此触发query has no destination for result data报错 - 存储过程中无法直接通过SELECT语句返回结果集,如果需要输出符合条件的买家信息,更适合使用返回表结构的函数,或者将结果写入临时表、通过日志打印输出
- 原有循环逻辑存在业务漏洞:你假设买家ID
id_buyer是从0开始连续递增的整数,实际业务中主键可能存在删除产生的缺口,会导致漏统计符合条件的用户
最优修改方案(抛弃循环,直接用关联查询实现,性能更高)
推荐直接使用返回表的函数实现需求,代码如下:
create or replace function bookstore.get_high_value_buyers() returns table ( id_buyer integer, name varchar, -- 请和你实际buyer表的字段类型保持一致 surname varchar, adress varchar ) language plpgsql as $$ begin return query select b.id_buyer, b.name, b.surname, b.adress from bookstore.buyer b join ( select id_buyer, sum(price) as total_consume from bookstore.receipt group by id_buyer having sum(price) > 1600 ) r on b.id_buyer = r.id_buyer; end $$;
调用方式:
select * from bookstore.get_high_value_buyers();
保留原有循环逻辑的修改方案
如果你需要保留原来的循环写法做调试,可以按如下修改,增加INTO赋值,同时用临时表存储结果:
create or replace procedure bookstore.procedure1 () language plpgsql as $$ declare i integer := 0; temp_sum numeric; number_of_buyers integer := (select max(id_buyer) from bookstore.buyer); -- 改用最大ID避免漏统计 begin -- 先创建临时表存结果 create temp table if not exists high_value_buyers ( id_buyer integer, name varchar, surname varchar, adress varchar ) on commit drop; while i <= number_of_buyers loop -- 增加INTO给temp_sum赋值 select sum(price) into temp_sum from bookstore.receipt where id_buyer = i; if temp_sum > 1600 then -- 把符合条件的结果插入临时表 insert into high_value_buyers select id_buyer, name, surname, adress from bookstore.buyer where id_buyer = i; end if; i := i+1; end loop; end $$;
调用方式:
call bookstore.procedure1(); select * from high_value_buyers;
内容的提问来源于stack exchange,提问作者Ice cream
相关产品推荐
相关产品推荐

