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

SQL Server删除重复记录异常:执行删除语句后所有记录被删除的问题排查

问题分析与解决方法

嘿,我来帮你揪出问题所在,再给你靠谱的解决方案~

你的删除语句为什么会全删?

你写的删除语句逻辑完全跑偏啦:

DELETE FROM TB_MOVIMENTO_PDV_DETALHE_PLANO_PAGAMENTO 
WHERE COD_PLANO_PAGAMENTO IN (
    SELECT MAX(COD_PLANO_PAGAMENTO) COD_PLANO_PAGAMENTO 
    FROM TB_MOVIMENTO_PDV_DETALHE_PLANO_PAGAMENTO 
    GROUP BY COD_PLANO_PAGAMENTO
)

这里的GROUP BY COD_PLANO_PAGAMENTO意味着把同一个COD_PLANO_PAGAMENTO的所有记录归为一组,每组的MAX(COD_PLANO_PAGAMENTO)就是这个COD本身啊!所以子查询返回的是所有存在的COD_PLANO_PAGAMENTO值,DELETE的时候自然就匹配了所有记录,直接全删了。

符合需求的正确删除逻辑

你的核心需求是:每个COD_MOVIMENTO下,相同COD_PLANO_PAGAMENTO的记录只保留一条(比如删除COD_MOVIMENTO=405且COD_PLANO_PAGAMENTO=9的第二条)。所以分组维度必须是COD_MOVIMENTO + COD_PLANO_PAGAMENTO,而不是单独的COD_PLANO_PAGAMENTO。

方法1:用窗口函数(推荐,适用于大多数现代数据库:MySQL8+/SQL Server/Oracle/PostgreSQL)

先执行查询确认要删除的记录(一定要先确认!):

SELECT *
FROM (
    SELECT 
        *,
        -- 按COD_MOVIMENTO+COD_PLANO_PAGAMENTO分组,给每组的记录编号
        ROW_NUMBER() OVER (
            PARTITION BY COD_MOVIMENTO, COD_PLANO_PAGAMENTO 
            ORDER BY COD_PLANO_PAGAMENTO -- 按COD排序,保留第一条;如果要保留最后一条,改成ORDER BY COD_PLANO_PAGAMENTO DESC
        ) AS rn
    FROM TB_MOVIMENTO_PDV_DETALHE_PLANO_PAGAMENTO
) t
WHERE rn > 1 -- 编号>1的就是重复的,需要删除

确认无误后,执行删除:

MySQL 8+版本写法:

DELETE t
FROM (
    SELECT 
        *,
        ROW_NUMBER() OVER (
            PARTITION BY COD_MOVIMENTO, COD_PLANO_PAGAMENTO 
            ORDER BY COD_PLANO_PAGAMENTO
        ) AS rn
    FROM TB_MOVIMENTO_PDV_DETALHE_PLANO_PAGAMENTO
) t
WHERE rn > 1

SQL Server/Oracle版本写法:

WITH CTE_Duplicates AS (
    SELECT 
        *,
        ROW_NUMBER() OVER (
            PARTITION BY COD_MOVIMENTO, COD_PLANO_PAGAMENTO 
            ORDER BY COD_PLANO_PAGAMENTO
        ) AS rn
    FROM TB_MOVIMENTO_PDV_DETALHE_PLANO_PAGAMENTO
)
DELETE FROM CTE_Duplicates WHERE rn > 1

方法2:关联删除(适用于不支持窗口函数的老版本数据库,比如MySQL 5.x)

同样先确认要删除的记录:

SELECT t1.*
FROM TB_MOVIMENTO_PDV_DETALHE_PLANO_PAGAMENTO t1
JOIN TB_MOVIMENTO_PDV_DETALHE_PLANO_PAGAMENTO t2 
    ON t1.COD_MOVIMENTO = t2.COD_MOVIMENTO 
    AND t1.COD_PLANO_PAGAMENTO = t2.COD_PLANO_PAGAMENTO
    AND t1.COD_PLANO_PAGAMENTO < t2.COD_PLANO_PAGAMENTO -- 保留COD更大的那条(最后一条);要保留第一条就改成>

确认后执行删除:

DELETE t1
FROM TB_MOVIMENTO_PDV_DETALHE_PLANO_PAGAMENTO t1
JOIN TB_MOVIMENTO_PDV_DETALHE_PLANO_PAGAMENTO t2 
    ON t1.COD_MOVIMENTO = t2.COD_MOVIMENTO 
    AND t1.COD_PLANO_PAGAMENTO = t2.COD_PLANO_PAGAMENTO
    AND t1.COD_PLANO_PAGAMENTO < t2.COD_PLANO_PAGAMENTO

重要提醒

执行删除操作前,一定要先备份数据,或者先运行对应的SELECT语句确认要删除的记录完全符合预期,避免误删哦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 19:23:11