You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL存储过程内调用colpivot报Query has no result错误

报错原因

colpivot函数执行时会动态生成指定名称的临时表,同时返回对应的透视结果集。在PL/pgSQL存储过程中,裸SELECT语句如果没有明确的结果接收目标(比如赋值给变量、写入表),数据库不会完整执行函数的全部逻辑,就会抛出Query has no result in destination data错误。
在客户端单独执行语句能正常运行,是因为SQL客户端会默认消费SELECT返回的结果集,函数内部的临时表生成逻辑可以完整执行;但存储过程中没有结果接收动作时,函数执行被截断,临时表未正常生成,后续建表读数据的逻辑自然也会触发异常。

修复方案

优先选择第一种方案,改动最小:

方案1:使用PERFORM执行colpivot,丢弃不需要的返回结果

后续逻辑是直接读取colpivot生成的_report临时表来创建物理表,不需要直接使用colpivot返回的结果集,用PL/pgSQL内置的PERFORM关键字执行函数即可——它会完整运行函数的全部逻辑生成临时表,同时丢弃冗余的返回结果,不会触发结果目标缺失的报错。
修改后的完整存储过程代码:

create or replace procedure create_report_table()
language plpgsql
as $$
begin

drop table if exists reports;

-- 将原SELECT改为PERFORM即可
perform colpivot('_report',
'select
u.username,
c.shortname as course_short_name,
to_timestamp(cp.timecompleted)::date as completed
FROM mdl_course_completions AS cp
JOIN mdl_course AS c ON cp.course = c.id
JOIN mdl_user AS u ON cp.userid = u.id
WHERE c.enablecompletion = 1
ORDER BY u.username' ,array['username'], array['course_short_name'], '#.completed', null);

create table reports as (SELECT * FROM _report);

commit;
end; $$

方案2:显式指定结果写入目标

如果不想使用PERFORM,也可以显式将colpivot的返回结果写入临时表,给查询明确的结果目的地,同样可以解决报错。注意执行前需要先清理可能存在的同名临时表,避免重名冲突:

-- 先清理同名临时表
drop table if exists _report;
-- 显式将colpivot结果写入临时表
create temp table _report as
select colpivot('_report',
'select
u.username,
c.shortname as course_short_name,
to_timestamp(cp.timecompleted)::date as completed
FROM mdl_course_completions AS cp
JOIN mdl_course AS c ON cp.course = c.id
JOIN mdl_user AS u ON cp.userid = u.id
WHERE c.enablecompletion = 1
ORDER BY u.username' ,array['username'], array['course_short_name'], '#.completed', null);
验证

修改完成后执行调用命令即可正常生成报表物理表:

call create_report_table();

内容的提问来源于stack exchange,提问作者Nilaksha Perera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 23:27:32