Sql-Server

BULK INSERT 繼續 PRIMARY KEY 錯誤

  • October 22, 2020

我每隔幾天就會收到一個包含幾百萬條記錄的 CSV 文件。我需要將它們插入到我們的數據庫中。我所做的很簡單:

BULK INSERT dbo.activity
FROM 'C:\tmp\activity.csv'
WITH (
   FIRSTROW = 2,
   FIELDTERMINATOR = '|',
   ROWTERMINATOR = '0x0a',
   BATCHSIZE = 1000,
   MAXERRORS = 2
)
GO

這很好用。但是,我可能會得到一些重複的記錄。當我執行導入時,如預期的那樣,得到錯誤:

Violation of PRIMARY KEY constraint 'PK__id__790FF7A****'. Cannot insert duplicate key in object 'dbo.activity'. The duplicate key value is (1234)

當我有數百條重複記錄而不是一條重複記錄時,這變得非常麻煩。有什麼方法可以告訴BULK INSERT忽略(或記錄)這些錯誤並繼續保持良好的記錄?我正在考慮類似的事情:

BEGIN TRY:
 BULK INSERT dbo.activity
 FROM 'C:\tmp\activity.csv'
 WITH (options....)
END TRY
BEGIN CATCH:
 SELECT
       ERROR_NUMBER() AS ErrorNumber  
      ,ERROR_MESSAGE() AS ErrorMessage;
  -- I know this line wrong.  It is just what I would like to do
 CONTINUE;
END CATCH

謝謝!

我認為一個好的方法是擁有一個臨時表(沒有 PK 約束)。

您將批量命令中的數據載入到此表中,然後,您應該能夠將要實現的邏輯編寫到可以在之後執行的儲存過程中

例如:檢查重複項,將它們記錄到另一個表或發送郵件,根據某些邏輯刪除重複項,然後將剩餘的行插入目標表中。

再次閱讀 BULK INSERT文件後,我認為這可能有效。它並不優雅,但對於我的場景來說它可以做到。它要求我知道文件中的記錄數。這很容易得到:

wc -l 'C:\tmp\activity.csv'

然後用那個數字我會做:

-- Let's suppose I have one million records (Usually I have several million)
DECLARE @max_records bigint = 1000000

BULK INSERT dbo.activity
FROM 'C:\tmp\activity.csv'
WITH (
   FIRSTROW = 2,
   FIELDTERMINATOR = '|',
   ROWTERMINATOR = '0x0a',
   BATCHSIZE = 1000,
   MAXERRORS = max_records,
   ERRORFILE = 'C:\tmp\bulik_insert.log'
)
GO

然後,只需仔細檢查日誌文件以確保錯誤與鍵約束有關,而不是其他問題。

我不知道這會給系統帶來多大的負擔。

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