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

T-SQL使用While循环与Cursor游标同步表差异返回重复记录的解决

问题根因

  • 插入逻辑错误:游标循环内的INSERT语句关联了整张#LocalTempTable,每遍历1条游标记录,就会批量插入和临时表总行数相等的重复数据,是数据重复的核心原因。
  • 业务逻辑不匹配:当前代码完全没有和Target表做id关联校验,无法区分「新增记录」和「已有记录更新」两种场景,分支逻辑也和需求要求的new_row/updated_row标注规则不符。
  • 性能冗余:这类数据对比场景完全可以用SQL集合操作实现,游标遍历的写法效率极低,不适合每日批量作业。

正确实现方案

不需要使用游标,直接用集合操作一次性写入结果即可:

INSERT INTO Result_Table (变更类型, id, New)
-- 匹配新增记录:Source有、Target没有的id
SELECT 
    'new_row' AS 变更类型,
    s.id,
    s.New
FROM Source s
LEFT JOIN Target t ON s.id = t.id
WHERE t.id IS NULL

UNION ALL

-- 匹配更新记录:两边id都存在,且Source的New字段更新为x或y
SELECT
    'updated_row' AS 变更类型,
    s.id,
    s.New
FROM Source s
INNER JOIN Target t ON s.id = t.id
WHERE s.New IN ('x','y')

如果确实需要保留游标写法做特殊逻辑扩展,修正后的游标代码如下:

DECLARE @id nvarchar(10) 
DECLARE @New  nvarchar(100)

DECLARE NewCursor CURSOR 
FOR
SELECT [id],[New] FROM #LocalTempTable 

OPEN NewCursor
FETCH NEXT FROM NewCursor INTO @id,@New

WHILE @@FETCH_STATUS = 0
BEGIN
    -- 先判断id是否存在于Target表
    IF NOT EXISTS (SELECT 1 FROM Target WHERE id = @id)
    BEGIN
        -- 不存在即为新增,插入1条
        INSERT INTO [Result_Table] (变更类型, id, New)
        VALUES ('new_row', @id, @New)
    END
    ELSE IF @New IN ('x','y')
    BEGIN
        -- 存在且New字段符合条件即为更新
        INSERT INTO [Result_Table] (变更类型, id, New)
        VALUES ('updated_row', @id, @New)
    END

    FETCH NEXT FROM NewCursor INTO @id,@New
END

CLOSE NewCursor
DEALLOCATE NewCursor

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 08:00:02