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

PostgreSQL 16中pg_cursors查询游标计数异常问题咨询

问题原因

PostgreSQL 16 调整了PL/pgSQL局部游标的可见性规则:你在过程里用DECLARE pg_cur CURSOR FOR ...声明的是局部游标,这类游标不会出现在系统视图pg_cursors里。但PostgreSQL 11里局部游标会被pg_cursors收录,所以原来靠查询pg_cursors判断的逻辑在16里失效,导致进不了循环。

解决方案

别再依赖pg_cursors做判断了,直接处理游标循环就行,或者用PL/pgSQL自带的游标状态属性:

方案1:删掉多余的检查,直接循环

改后的存储过程如下:

CREATE OR REPLACE PROCEDURE gis_in.pg_cur_test1()
LANGUAGE 'plpgsql'
AS $BODY$
DECLARE
    m_bref numeric;
    pg_cur CURSOR FOR SELECT id FROM emp;
BEGIN   
   OPEN pg_cur;
   FETCH pg_cur INTO m_bref;
   LOOP
        EXIT WHEN NOT FOUND;
        RAISE INFO 'm_bref is :,%', m_bref;
        FETCH pg_cur INTO m_bref;
   END LOOP;
   RAISE INFO 'Loop finished';
   CLOSE pg_cur;
END;
$BODY$;

方案2:用游标属性判断是否打开(如果需要状态检查)

要是你确实得确认游标是否打开,用PL/pgSQL自带的%ISOPEN属性就行,比查pg_cursors靠谱:

CREATE OR REPLACE PROCEDURE gis_in.pg_cur_test1()
LANGUAGE 'plpgsql'
AS $BODY$
DECLARE
    m_bref numeric;
    pg_cur CURSOR FOR SELECT id FROM emp;
BEGIN   
   OPEN pg_cur;
   FETCH pg_cur INTO m_bref;
   IF pg_cur%ISOPEN THEN
     LOOP
          EXIT WHEN NOT FOUND;
          RAISE INFO 'm_bref is :,%', m_bref;
          FETCH pg_cur INTO m_bref;
     END LOOP;
   END IF;
   RAISE INFO 'Loop processing done';
   CLOSE pg_cur;
END;
$BODY$;

额外优化:更简洁的游标写法

其实PL/pgSQL支持直接用FOR...IN遍历游标结果,不用手动打开、关闭游标,代码更简洁:

CREATE OR REPLACE PROCEDURE gis_in.pg_cur_test1()
LANGUAGE 'plpgsql'
AS $BODY$
DECLARE
    m_bref numeric;
BEGIN   
   FOR m_bref IN SELECT id FROM emp LOOP
        RAISE INFO 'm_bref is :,%', m_bref;
   END LOOP;
   RAISE INFO 'Loop completed';
END;
$BODY$;

内容的提问来源于stack exchange,提问作者Gopal.anant

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 16:22:45