2012-05-23 27 views
6

Tôi có một SQL Server 2008 nhiều-nhiều bảng quan hệ (Assets) với hai cột:MERGE Vi phạm TIỂU chế KEY

AssetId (PK, FK, uniqueidentifier, not null) 
AssetCategoryId (PK, FK, int, not null) 

Trong dự án của tôi, tôi cần phải thực hiện các hàng từ bảng này, và chèn chúng vào cơ sở dữ liệu được sao chép định kỳ. Vì vậy, tôi có hai cơ sở dữ liệu được chính xác giống nhau (bao gồm các ràng buộc).

Để "sao chép" từ cơ sở dữ liệu này sang cơ sở dữ liệu khác, tôi sử dụng câu lệnh MERGE với bảng tạm thời. Tôi chèn lên đến 50 bản ghi vào bảng temp, sau đó hợp nhất các bảng temp với Assets bảng tôi sao chép vào như sau:

CREATE TABLE #Assets (AssetId UniqueIdentifier, AssetCategoryId Int); 
INSERT INTO #Assets (AssetId, AssetCategoryId) VALUES ('ed05bac3-7a92-46aa-8822-2d882b137597', 44), ('dc5e3082-e2eb-4bdf-a640-94e0f59411ed', 22) ... ; 

MERGE INTO Assets WITH (HOLDLOCK) AS Target 
USING #Assets AS Source 
ON Target.AssetId = Source.AssetId AND Target.AssetCategoryId = Source.AssetCategoryId 
WHEN MATCHED THEN 
UPDATE SET ... 
WHEN NOT MATCHED BY Target THEN 
INSERT (AssetId,AssetCategoryId) VALUES (Source.AssetId,Source.AssetCategoryId); 

này hoạt động tuyệt vời, cho hầu hết các phần. Tuy nhiên, một lần trong một thời gian, tôi nhận được lỗi:

Violation of PRIMARY KEY constraint 'PK_Assets'. Cannot insert duplicate key in object 'dbo.Assets'. The duplicate key value is (dc5e3082-e2eb-4bdf-a640-94e0f59411ed, 22). The statement has been terminated.

Khi tôi kiểm tra trong bảng Assets, không có hồ sơ như vậy tồn tại ... vì vậy tôi đang bối rối thế nào tôi sẽ được chèn một khóa trùng lặp.

Bất kỳ ý tưởng gì đang xảy ra ở đây?

CẬP NHẬT

Khi thử nghiệm, nó chạy thành công 6 lần, chèn 300 dòng. Vào lần thử thứ 7, nó luôn đưa ra cùng một lỗi được hiển thị ở trên. Hơn nữa, khi tôi INSERT(dc5e3082-e2eb-4bdf-a640-94e0f59411ed, 22) của chính nó, nó hoạt động tốt. Thử nghiệm của tôi sau đó có thể tiếp tục và chèn các hàng còn lại không có lỗi.

+0

Tuyên bố hợp nhất được biết là có lỗi. Có thể bạn đã đánh một. Vui lòng đăng kế hoạch thực hiện. – usr

Trả lời

12

Bạn cần thêm HOLDLOCK vào tuyên bố MERGE của mình. Hãy thử các cách sau:

MERGE INTO Assets WITH (HOLDLOCK) AS Target 
... 

Điều này tránh tình trạng cuộc đua mà bạn đang gặp phải. Xem thêm thông tin here

EDIT

Dựa trên bản cập nhật của bạn, chỉ có điều khác tôi có thể nghĩ đến là bảng temp của bạn có thể có một kỷ lục trùng lặp trong đó. Bạn có thể kiểm tra lại không?

+0

Cảm ơn bạn đã phản hồi nhanh. Bạn có thể đã cứu tôi (và những người khác) một số nhức đầu trong tương lai, nhưng tiếc là điều này đã không khắc phục được vấn đề của tôi. Vui lòng xem câu hỏi được cập nhật. – Justin

+2

Bạn đúng 100%. Tôi đã có một bản sao trong bảng tạm thời của tôi. Đoán lời khuyên HOLDLOCK chỉ là tiền thưởng! – Justin