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

SQL代码返回线性递增重复数据的问题排查与修复请求

问题描述

我的SQL代码在运行9天周期(今日往前推8天)的同步任务时,插入dbo.finaltable的数据出现重复:今日的每条数据对应1行,昨日对应2条相同值,往前2天对应3条重复数据,直到第8天对应9条重复数据。代码如下:

declare @CurDate datetime

-- Redo the last 7 days of transactions
select @CurDate = cast(cast(dateadd(dd,-8,getdate()) as char(11)) as datetime)

TRUNCATE TABLE dbo.finaltable

WHILE @Curdate <= getdate()
BEGIN
    DECLARE @temp table
(
    [StatsType] [char](5) NOT NULL,
    [EquipmentNo] [int] NOT NULL,
    [EquipmentType] [char](1) NOT NULL,
    [Terminal] [char](1) NOT NULL,
    [Param] [char](200) NULL,
    [Date] [datetime] NULL,
    [Error] [bit] NULL,
    [DayKey] [char](8) NULL,
    [TimeKey] [char](4) NULL,
    [DateTimeKey] bigint
)

    INSERT @temp EXEC SQLPRDC.serv.dbo.prproc @CurDate

    INSERT dbo.finaltable
(
    [StatsType]
    ,[EquipmentNo]
    ,[EquipmentType]
    ,[Terminal]
    ,[Param]
    ,[Date]
    ,[Error]
    ,[DayKey]
    ,[TimeKey]
    ,[DateTimeKey]
)
SELECT
        [StatsType]
    ,[EquipmentNo]
    ,[EquipmentType]
    ,[Terminal]
    ,[Param]
    ,[Date]
    ,[Error]
    ,[DayKey]
    ,[TimeKey]
    ,[DateTimeKey]
FROM @temp
WHERE EquipmentType = 'M'

    SELECT @CurDate = dateadd(dd,1,@CurDate)
END

对比之下,同类存储过程prproca无需临时表过滤即可正常运行,代码如下:

declare @CurDate datetime 
-- Redo the last 7 days of transactions 
select @CurDate = cast(cast(dateadd(dd,-8,getdate()) as char(11)) as datetime) 

TRUNCATE TABLE dbo.finaltable 

WHILE @Curdate <= getdate() 
BEGIN 
INSERT dbo.finaltable EXEC SQLPRDC.Rtostats.dbo.prproca @CurDate 

SELECT @CurDate = dateadd(dd,1,@CurDate) 

END
原因分析

核心问题出在存储过程prproc的逻辑上:它不是仅返回传入参数@CurDate当天的数据,而是返回从某个起始日期到@CurDate的所有历史数据。

循环执行时:

  • 第一次循环(@CurDate=8天前):返回8天前的数据,插入finaltable
  • 第二次循环(@CurDate=7天前):返回8天前+7天前的数据,过滤后插入,导致8天前的数据被重复插入一次
  • ...
  • 第九次循环(@CurDate=今日):返回8天前到今日的所有数据,过滤后插入,8天前的数据累计被插入9次,以此类推

而prproca能正常运行,说明它的逻辑是仅返回传入日期当天的数据,不会包含历史累积数据。

修复方案

方案1:修改存储过程prproc(根治)

检查并调整prproc的内部逻辑,确保它只返回传入参数@CurDate当天的统计数据,这是最彻底的解决办法,从源头避免重复数据。

方案2:在现有代码基础上做去重处理(无需修改存储过程)

如果无法修改prproc,可以在插入finaltable时加入去重逻辑,以下是两种可行方式:

方式A:每次插入前先清理对应日期的数据

在循环内插入前,先删除finaltable中当前@CurDate且EquipmentType='M'的数据,再插入临时表的过滤结果:

declare @CurDate datetime

select @CurDate = cast(cast(dateadd(dd,-8,getdate()) as char(11)) as datetime)

TRUNCATE TABLE dbo.finaltable

WHILE @Curdate <= getdate()
BEGIN
    DECLARE @temp table
(
    [StatsType] [char](5) NOT NULL,
    [EquipmentNo] [int] NOT NULL,
    [EquipmentType] [char](1) NOT NULL,
    [Terminal] [char](1) NOT NULL,
    [Param] [char](200) NULL,
    [Date] [datetime] NULL,
    [Error] [bit] NULL,
    [DayKey] [char](8) NULL,
    [TimeKey] [char](4) NULL,
    [DateTimeKey] bigint
)

    INSERT @temp EXEC SQLPRDC.serv.dbo.prproc @CurDate

    -- 新增:删除当前日期已存在的目标数据
    DELETE FROM dbo.finaltable
    WHERE EquipmentType = 'M'
      AND CONVERT(date, [Date]) = CONVERT(date, @CurDate)

    INSERT dbo.finaltable
(
    [StatsType]
    ,[EquipmentNo]
    ,[EquipmentType]
    ,[Terminal]
    ,[Param]
    ,[Date]
    ,[Error]
    ,[DayKey]
    ,[TimeKey]
    ,[DateTimeKey]
)
SELECT
        [StatsType]
    ,[EquipmentNo]
    ,[EquipmentType]
    ,[Terminal]
    ,[Param]
    ,[Date]
    ,[Error]
    ,[DayKey]
    ,[TimeKey]
    ,[DateTimeKey]
FROM @temp
WHERE EquipmentType = 'M'
  -- 新增:只取当前日期的数据
  AND CONVERT(date, [Date]) = CONVERT(date, @CurDate)

    SELECT @CurDate = dateadd(dd,1,@CurDate)
END

方式B:插入时使用DISTINCT去重(如果无唯一键约束)

如果finaltable没有唯一键约束,可以在插入的SELECT语句中加入DISTINCT,确保每条数据只插入一次:

-- 仅修改插入部分的SELECT语句
INSERT dbo.finaltable
(
    [StatsType]
    ,[EquipmentNo]
    ,[EquipmentType]
    ,[Terminal]
    ,[Param]
    ,[Date]
    ,[Error]
    ,[DayKey]
    ,[TimeKey]
    ,[DateTimeKey]
)
SELECT DISTINCT -- 新增DISTINCT
        [StatsType]
    ,[EquipmentNo]
    ,[EquipmentType]
    ,[Terminal]
    ,[Param]
    ,[Date]
    ,[Error]
    ,[DayKey]
    ,[TimeKey]
    ,[DateTimeKey]
FROM @temp
WHERE EquipmentType = 'M'

方式C:一次性获取所有数据后去重插入

可以把循环去掉,直接一次调用prproc传入今日日期,获取所有8天内的数据,过滤后去重插入:

declare @CurDate datetime
select @CurDate = cast(getdate() as date)

TRUNCATE TABLE dbo.finaltable

DECLARE @temp table
(
    [StatsType] [char](5) NOT NULL,
    [EquipmentNo] [int] NOT NULL,
    [EquipmentType] [char](1) NOT NULL,
    [Terminal] [char](1) NOT NULL,
    [Param] [char](200) NULL,
    [Date] [datetime] NULL,
    [Error] [bit] NULL,
    [DayKey] [char](8) NULL,
    [TimeKey] [char](4) NULL,
    [DateTimeKey] bigint
)

INSERT @temp EXEC SQLPRDC.serv.dbo.prproc @CurDate

INSERT dbo.finaltable
(
    [StatsType]
    ,[EquipmentNo]
    ,[EquipmentType]
    ,[Terminal]
    ,[Param]
    ,[Date]
    ,[Error]
    ,[DayKey]
    ,[TimeKey]
    ,[DateTimeKey]
)
SELECT DISTINCT
        [StatsType]
    ,[EquipmentNo]
    ,[EquipmentType]
    ,[Terminal]
    ,[Param]
    ,[Date]
    ,[Error]
    ,[DayKey]
    ,[TimeKey]
    ,[DateTimeKey]
FROM @temp
WHERE EquipmentType = 'M'
  AND [Date] >= dateadd(dd,-8,getdate())

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 15:07:35