Sql-Server

SQL插入具有唯一約束的多個值

  • April 10, 2017

我有一個 MS SQL Server 2012 和下表:

CREATE TABLE dzp.contractid (
id bigint PRIMARY KEY IDENTITY(1,1),
VNR char(18) NOT NULL,
CONSTRAINT UC_VNR UNIQUE (VNR))

對於上下文,VNR 表示字元串形式的唯一契約編號。

我想導入包含契約資訊的 csv 文件,每個契約可能包含多行。為了避免對 char(18) 進行查詢,我試圖在使用暫存表的 INSERT-Trigger 載入時對數據進行規範化。

流程是:

csv-file --> staging table --> insert trigger --> normalized tables

在我的觸發器中,我正在嘗試以下操作:

BEGIN TRY
   INSERT INTO dzp.contractid(VNR)
   SELECT VNR
   FROM dzp.accounts_stage
END TRY

BEGIN CATCH
-- ignore unique constraint violation error, raise otherwise
IF ERROR_NUMBER() <> 2627
   RAISERROR ('blah', 16, 1)
END CATCH

所以我希望實現的基本上是:

  1. 從臨時表中獲取所有契約號
  2. 將所有這些數字添加到規範化表中
  3. 忽略違反唯一約束時引發的錯誤
  4. 正常工作時,我現在有一個包含所有唯一 VNR 的表

問題:

Uniqueness-Constraint 似乎阻止了整個 INSERT,而不僅僅是實際重複的值。

是否有某種方法可以逐行插入數據,或者告訴約束逐行處理它?

這甚至是正確的方法嗎?我很高興完全改變這種方法,因為我無法想像我是第一個遇到這個問題的人……就上下文而言,這本質上是一個報告數據庫,每天批處理一次,總共大約 100 萬行(來自 csv 表),並且有大約 5 個使用者不時執行查詢。

感謝您的輸入!

SQL 約束違反影響整個語句,您不能忽略個別行。

可以做的是僅插入不違反約束的行。有幾種方法可以做到這一點,例如

INSERT INTO dzp.contractid(vnr)
SELECT DISTINCT vnr FROM dzp.accounts_stage s 
WHERE NOT EXISTS (SELECT 1 FROM dzp.contractid WHERE vnr = s.vnr)

你也可以使用MERGE

MERGE dzp.contractid AS t
USING dzp.accounts_stage AS s
ON (t.vnr = s.vnr) 
WHEN NOT MATCHED BY TARGET 
THEN INSERT(vnr) VALUES(s.vnr)

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