【问题标题】:SQL Server Stored Procedure Creating DuplicatesSQL Server 存储过程创建副本
【发布时间】:2025-12-20 02:05:11
【问题描述】:

我正在使用 SQL Server 2008 和 ASP.NET 4.0 运行一个网站。我试图追踪一个问题,即我的存储过程正在为同一日期创建重复条目。最初我认为这可能是几个帖子问题,但重复记录的日期相同,精确到毫秒。其中一个重复项位于:'2013-04-26 15:48:28.323' 除 id 外,所有数据都完全相同。

@check_date 是存储过程的输入,它为我们提供了我们正在查看的特定日期(条目是每天的女仆)

@formHeaderId 在存储过程的早期被抓取,获取标头 ID,因为这是一个与标头具有一对多关系的详细信息表。

@getdate() 条目是我找到重复条目的地方,不同行的 getdate() 值完全相同。

这也不会发生在每个条目中,它是在应用程序中随机发生的。

select @formHeaderId=stage2_checklist_header_id 
from stage2_checklist_header 
where environmental_forms_id=@envFormId
and checklist_monthyear=@inspected_month 
order by start_date desc

if @formHeaderId = 0 begin

    insert into stage2_checklist_header(
        environmental_forms_id      
        ,start_date 
        ,checklist_monthyear
        ,st2h_load_date )
    values( @envFormId
            ,@check_date 
            ,@inspected_month 
            ,getdate())

    set @formHeaderId = scope_identity() 
    print 'inserted new header record ' + cast(@formHeaderId as varchar(50))

end 

IF (NOT EXISTS(
       SELECT *
         FROM stage2_checklist_detail
        WHERE  stage2_checklist_header_id = @formHeaderId
          AND check_date = @check_date
    ))
INSERT INTO stage2_checklist_detail
  (stage2_checklist_header_id, check_date, st2_chk_det_load_date, 
   inspected_by)
VALUES
  (@formHeaderId, @check_date, GETDATE(), @inspected_by)

SET @form_detail_id = SCOPE_IDENTITY()
    PRINT 'inserted detail record ' + CAST(@form_detail_id AS VARCHAR(50)) 

【问题讨论】:

  • 您是否有任何与此 sp 关联的触发器?
  • "除了id,所有的数据都完全一样。"在您的支票中,您正在寻找匹配的 ID。如果不同,则插入一行。
  • 在这段代码中很难看出重复插入的可能性。您的应用程序代码的两个线程是否可能同时运行此过程?他们可能会达到相同的毫秒数。还是程序内部有循环?
  • 具体来说,两个线程可以精确地避开 EXISTS 检查,因为它们达到了相同的毫秒数。这也可以解释重复插入的间歇性(或随机性)性质。
  • 这似乎是用户输入问题,是否有可能两个人同时尝试插入相同的数据?我要做的是将存在检查数据逻辑包装在一个转换语句中,以消除毫秒差异并查看是否修复了您的重复项。只是一个想法,还有其他选择。

标签: asp.net sql stored-procedures sql-server-2000


【解决方案1】:

这是一个similar case,开发人员能够在其中跟踪来自不同 spid 的同时调用的重复条目(这回避了 EXISTS 检查)。在尝试了隔离级别和事务之后——并试图避免死锁——听起来这种情况下的解决方案是使用 sp_getapplock 和 sp_releaseapplock。

【讨论】:

    【解决方案2】:

    NOT EXISTS 检查中,您正在查找具有相同 ID 和相同日期的记录。因此,如果表中不存在 ID 和日期的组合,则将插入该行。 在您对问题的描述中,您声明“所有数据都完全相同,除了 id”。 ID 不同将始终根据您用于检查是否存在的逻辑导致 INSERT。

    【讨论】:

    • 我认为 OP 是在谈论 stage2_checklist_detail_id,而不是 stage2_checklist_header_id。在这部分代码中,我们只看到变量 (at)form_detail_id 和 (at)formHeaderId。
    • 是的,这是正确的。该声明的意思是“除了 stage2_checklist_detail_id 之外的所有数据都是相同的”。 stage2_checklist_detail_id 是在插入时生成的自增主键字段。如果表中已经存在stage2_checklist_header_id和check_date,则不应再插入一行。
    最近更新 更多