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

动态游标删除记录后仍被抓取,存储过程报错Msg16929排查

问题分析与解决方案

核心问题1:游标只读导致删除报错(Msg 16929)

动态游标(DYNAMIC)默认不具备可更新权限,必须在声明游标时显式指定FOR UPDATE子句,才能允许通过游标执行数据修改操作。如果你的游标没有添加该子句,直接在循环中尝试删除临时表记录,SQL Server会判定游标为只读,触发Msg 16929错误。

核心问题2:外部删除导致游标继续遍历已删除记录

如果你的删除操作是直接针对临时表(比如DELETE FROM #temp_fuel_que WHERE FUEL_NAME IN ('GCXFTSLOSS','GCXFTSUAF'))而非通过游标语法(DELETE WHERE CURRENT OF 游标名),动态游标无法感知这种外部修改。动态游标仅会追踪通过自身执行的修改操作,外部删除不会同步到游标结果集,因此游标仍会尝试遍历原有的三条记录,导致抓取已删除的无效行。

修正方案

方案1:正确配置可更新游标并通过游标删除记录

声明游标时添加FOR UPDATE子句,使用DELETE WHERE CURRENT OF语法删除当前游标指向的行,这样游标会自动感知行删除,循环会在有效行处理完后终止:

DECLARE @FuelName VARCHAR(50)

DECLARE fuel_cursor CURSOR DYNAMIC
FOR SELECT FUEL_NAME FROM #temp_fuel_que
FOR UPDATE -- 赋予游标更新权限

OPEN fuel_cursor
FETCH NEXT FROM fuel_cursor INTO @FuelName

WHILE @@FETCH_STATUS = 0
BEGIN
    IF @FuelName <> 'GCXFTSFUEL'
    BEGIN
        DELETE FROM #temp_fuel_que WHERE CURRENT OF fuel_cursor -- 通过游标删除当前行
    END

    FETCH NEXT FROM fuel_cursor INTO @FuelName
END

CLOSE fuel_cursor
DEALLOCATE fuel_cursor

方案2:避免游标,使用直接DML语句(更高效)

如果你的需求只是保留第一条记录、删除其余所有行,完全不需要游标,直接执行删除语句即可,性能远优于游标:

DELETE FROM #temp_fuel_que WHERE FUEL_NAME <> 'GCXFTSFUEL'

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 14:17:29