2010-01-25 102 views
4

奇怪的問題。我在表中插入10,000條左右的記錄,主鍵不是標識字段。所以當插入所有10,000如果一些是重複的,有沒有辦法跳到sql server插入下一個記錄,並確保非重複進入?我真的不關心重複沒有插入。主鍵重複記錄繞過到下一個插入

回答

8

使用「忽略重複密鑰」選項。

最簡單的方法是刪除SQL Server Management Studio中的主鍵。

然後創建一個新索引,類型爲「索引」,設置唯一爲「是」,並將「忽略重複鍵」設置爲「是」。然後插入你的記錄。它會插入除重複項以外的所有項目。完成後,您可以刪除此索引,然後重新創建主鍵。

如果你想有一個TSQL方法,請參閱CREATE INDEX呼叫IGNORE_DUP_KEY選項:

CREATE INDEX (Transact-SQL)

編輯:

源之間的另一種方法是使用LEFT JOIN表和要插入的記錄以及GROUP BY子句,只插入源中不存在的記錄。 GROUP BY將消除新記錄中的重複項。

+0

爲主鍵? – uirn 2010-01-25 22:56:35

+1

主鍵不會被違反,違規記錄會創建警告而不回滾整個批量插入。 – JeffO 2010-01-25 23:02:32

0

有幾種方法可以解決,因爲我不知道用什麼機制來完成插入操作。

1)將所有記錄批量加載到一個新的空表中,然後從該臨時表中運行一個INSERT到實際表中,其中該記錄尚不存在於主表中。 例如

INSERT MyRealTable (PKField, Field1) 
SELECT x.PKField, x.Field1 
FROM MyStagingTable x 
    LEFT JOIN MyRealTable r ON x.PKField = r.PKField 
WHERE r.PKField IS NULL 

2)包裝每個插入在TRY...CATCH塊吞下PK約束錯誤應該發生(如果你使用SQL 2005或更高版本)。

+0

不是新的記錄不會被複制,不僅僅是現有的新記錄 – uirn 2010-01-25 22:57:08

+0

使用選項1,您只需將每個PKField值的一條記錄從暫存表中拖到實際表中。例如您可以在登臺表上擁有一個IDENTITY列,並獲取每個PKField值的第一個實例。 – AdaTheDev 2010-01-25 23:01:03

2

這個例子查詢通過PK1跳過重複的行:

INSERT INTO Dest (PK1, Field2) 
SELECT s.PK1, s.F2 
FROM Source s 
WHERE 
(
    SELECT TOP 1 d.PK1 
    FROM Dest d 
    WHERE d.PK1 = s.PK1 
) IS NULL 
5

你需要定義主鍵忽略重複:

CREATE TABLE [dbo].[t2](
     [n] [int] NOT NULL, 
PRIMARY KEY CLUSTERED 
(
     [n] ASC 
)WITH (IGNORE_DUP_KEY = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 

使用此選項可能會降低性能:

如果你的數據只有一小部分重複,然後IGNORE_DUP_KEY可能會加速你的插入。對於大量的重複,IGNORE_DUP_KEY可能會顯着減慢它們的速度。我設置了兩個表,剝離了所有無關的細節,如下:

​​

如果輸入的數據有沒有重複,無論是刀片的性能始終是相同的:

INSERT t1(n) 
SELECT n FROM dbo.Numbers 

INSERT t2(n) 
SELECT n FROM dbo.Numbers 

(注那個dbo數字有100萬行)當然,我總是在兩次測試之間截斷兩個表。

如果傳入的數據有重複的1%,與IGNORE_DUP_KEY插入件一致的方式進行快大約5%:

INSERT t1(n) 
SELECT DISTINCT n FROM(
SELECT n FROM dbo.Numbers 
UNION ALL 
SELECT n FROM dbo.Numbers WHERE n <10000 
) AS t 

INSERT t2(n) 
SELECT n FROM dbo.Numbers 
UNION ALL 
SELECT n FROM dbo.Numbers WHERE n <10000 

在另一方面,如果輸入數據具有重複的100%時,所述插入件與IGNORE_DUP_KEY一致的方式進行慢至少300%,都爲一大組200萬行:

INSERT t1(n) 
SELECT DISTINCT n FROM(
SELECT n FROM dbo.Numbers 
UNION ALL 
SELECT n FROM dbo.Numbers 
) AS t 

INSERT t2(n) 
SELECT n FROM dbo.Numbers 
UNION ALL 
SELECT n FROM dbo.Numbers 

以及針對較小的一組的行200K:

INSERT t1(n) 
SELECT DISTINCT n FROM(
SELECT n FROM dbo.Numbers WHERE n<100000 
UNION ALL 
SELECT n FROM dbo.Numbers WHERE n<100000 
) AS t 

INSERT t2(n) 
SELECT n FROM dbo.Numbers WHERE n<100000 
UNION ALL 
SELECT n FROM dbo.Numbers WHERE n<100000 

總體而言,我決定在我的特殊情況下不使用IGNORE_DUP_KEY。我決定少量重複數據的少量節省不能證明大量重複數據的巨大性能下降的風險。