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

PostgreSQL使用WHERE CURRENT OF报错:游标不存在问题排查

问题描述

创建临时表AMB_LOMB:

CREATE TEMPORARY TABLE AMB_LOMB
( azienda_usl           char(3),
ospedale                char(6) ,
numero_riga             integer NOT NULL PRIMARY KEY,
codice_associazione char(5),
errore              varchar(3),
riferimento_errore varchar(10) , 
errore_grave        integer ,
id_pai              varchar(32) ) 
ON COMMIT PRESERVE ROWS ;

编写存储过程public.lomb_amb2019_SUBtest_0用于校验并更新该表:

CREATE OR REPLACE PROCEDURE public.lomb_amb2019_SUBtest_0()
LANGUAGE 'plpgsql'
AS $BODY$
    declare     zio record ;
                m_errore char(3);
                m_errore_grave integer;
                

begin
    for zio in 
    select     azienda_usl as                 _azienda_usl,      
                errore_grave ,     
                numero_riga as                 _numero_riga,      
                errore            
    from amb_lomb 
    for update      
    loop 

        -- 执行一些计算和设置操作
    
        m_errore_grave := '0' ;
        m_errore       := '   ' ;
                
        update amb_lomb 
        set errore_grave=m_errore_grave, errore=m_errore
        where current of zio ;
        
    end loop ;

end;
$BODY$;

执行call lomb_amb2019_SUBtest_0() ;时触发错误:

ERROR:  游标"zio"不存在
CONTEXT:  SQL语句"update amb_lomb 
        set errore_grave=m_errore_grave, errore=m_errore
        where current of zio"
PL/pgSQL函数lomb_amb2019_subtest_0()第22行的SQL语句

ERRORE:  游标"zio"不存在
SQL state: 34000

但其他结构类似的存储过程操作同一张表却未报错,请问问题原因是什么?


问题原因及解决办法

核心原因

PostgreSQL的PL/pgSQL中,FOR ... IN SELECT这种隐式循环使用的是匿名隐式游标,而WHERE CURRENT OF语法仅支持显式声明的命名游标。你代码里的zio是循环迭代的record变量,并非游标对象,因此无法被WHERE CURRENT OF识别,导致报错“游标不存在”。

其他存储过程未报错的原因

那些存储过程大概率没有使用WHERE CURRENT OF,而是通过表的主键(如numero_riga)来定位更新行,或者显式声明了命名游标并正确使用。

修复方案

有两种常用修复方式:

  • 通过主键字段更新(推荐):
    利用表的主键numero_riga作为更新条件,直接用循环中获取的_numero_riga匹配:

    update amb_lomb 
    set errore_grave=m_errore_grave, errore=m_errore
    where numero_riga = zio._numero_riga;
    
  • 显式声明命名游标:
    先定义命名游标,再执行打开、循环、关闭操作,此时即可正常使用WHERE CURRENT OF:

    CREATE OR REPLACE PROCEDURE public.lomb_amb2019_SUBtest_0()
    LANGUAGE 'plpgsql'
    AS $BODY$
        declare     
            cur_zio cursor for 
                select azienda_usl as _azienda_usl,      
                       errore_grave,     
                       numero_riga as _numero_riga,      
                       errore            
                from amb_lomb 
                for update;
            zio record;
            m_errore char(3);
            m_errore_grave integer;
    
    begin
        open cur_zio;
        loop
            fetch cur_zio into zio;
            exit when not found;
    
            m_errore_grave := '0' ;
            m_errore       := '   ' ;
                     
            update amb_lomb 
            set errore_grave=m_errore_grave, errore=m_errore
            where current of cur_zio;
            
        end loop;
        close cur_zio;
    end;
    $BODY$;
    

内容的提问来源于stack exchange,提问作者Andrea Ricci

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 01:19:57