Insert

插入時如何避免主鍵衝突

  • June 1, 2018

我有一個從原始碼插入目標表的程式碼,但有時我們會遇到死鎖。

由於死鎖,我必須再次重新執行此程式碼。

當我重新執行時,我最終違反了主鍵。因此,我想添加一個檢查以僅插入那些不存在的行。

有人可以幫我解決這個問題嗎?

   declare @batchSize int = 1000
   INSERT INTO [dbo].[Destinationtable]
      ([PacketId]
      ,[DeviceId]
      ,[PacketDate]
      ,[PacketNumber]
      ,[Processed]
      ,[CreateDate]
      ,[NewReadingId])
SELECT top (@batchSize)
      [PacketId]
     ,[DeviceId]
     ,[PacketDate]
     ,[PacketNumber]
     ,[Processed]
     ,[CreateDate]
     ,newid()
 FROM [dbo].[SourceTable]
 where Processed is null 
 order by CreateDate

死鎖後執行時出現錯誤消息

違反 PRIMARY KEY 約束“PK_packetid”。無法在對象“dbo.destinationtable”中插入重複鍵。重複鍵值為(1234567)。

使用不存在

declare @batchSize int = 1000
INSERT INTO [dbo].[Destinationtable]
  ([PacketId]
  ,[DeviceId]
  ,[PacketDate]
  ,[PacketNumber]
  ,[Processed]
  ,[CreateDate]
  ,[NewReadingId])
SELECT top (@batchSize)
  [PacketId]
 ,[DeviceId]
 ,[PacketDate]
 ,[PacketNumber]
 ,[Processed]
 ,[CreateDate]
 ,newid()
FROM [dbo].[SourceTable]
where Processed is null  
 and not exists (select 1 from [Destinationtable] 
                 where [PacketId] = [SourceTable].[PacketId])
order by CreateDate

我懷疑插入數據和更新處理的事務有問題,它們應該是原子的。發生錯誤時,您應該回滾事務並處於安全的基礎上,以便您可以重新啟動事務。

但是,您可以嘗試 MERGE:

MERGE [dbo].[Destinationtable] as x
USING (
   SELECT top (@batchSize) [PacketId]
   ,[DeviceId]
   ,[PacketDate]
   ,[PacketNumber]
   ,[Processed]
   ,[CreateDate]
   ,newid()
   FROM [dbo].[SourceTable]
   where Processed is null 
   order by CreateDate
) y 
   ON x.<key> = <y.key>
WHEN NOT MATCHED THEN
   INSERT (<columns>)
   VALUES (...);

引用自:https://dba.stackexchange.com/questions/208471