2012-05-23 19 views
6

Ho uno SQL Server 2008 molti-a-molti tabella di relazione (Assets) con due colonne:MERGE violazione di vincolo PRIMARY KEY

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

nel mio progetto, ho bisogno di prendere le righe di questa tabella, e inserirli periodicamente in un database replicato. Quindi, ho due database che sono esattamente uguali (vincoli inclusi).

Per "copiare" da un database all'altro, utilizzo un'istruzione MERGE con una tabella temporanea. Inserisco fino a 50 record nella tabella temporanea, quindi unire la tabella temporanea con la tabella Assets sto copiando in modo seguente:

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); 

Questa grande opera, per la maggior parte. Tuttavia, una volta ogni tanto, ottengo l'errore:

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.

Quando controllo nella tabella Assets, non esiste un tale record ... quindi mi sono confuso come mi sarebbe l'inserimento di una chiave duplicata.

Qualche idea di cosa sta succedendo qui?

UPDATE

Quando il test, viene eseguito con successo 6 volte, l'inserimento di 300 righe. Al settimo tentativo, dà sempre lo stesso errore mostrato sopra. Inoltre, quando I INSERT(dc5e3082-e2eb-4bdf-a640-94e0f59411ed, 22) da solo, funziona correttamente. Il mio test è quindi in grado di continuare e inserire le righe rimanenti senza errori.

+0

L'istruzione di unione è nota per avere bug. Forse ne hai colpito uno. Per favore pubblica il piano di esecuzione. – usr

risposta

12

È necessario aggiungere un HOLDLOCK all'istruzione MERGE. Prova il seguente:

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

Questo evita la condizione di gara in cui ti stai imbattendo. Vedere ulteriori informazioni here

EDIT

Sulla base della sua aggiornamento, l'unica altra cosa che posso pensare è che la tabella temporanea potrebbe avere un record duplicato in esso. Puoi ricontrollare?

+0

Grazie per la rapida risposta. Probabilmente hai salvato me (e altri) mal di testa in futuro, ma sfortunatamente questo non ha risolto il mio problema. Si prega di consultare la domanda aggiornata. – Justin

+2

Sei corretto al 100%. Ho avuto un duplicato nel mio tavolo temporaneo. Indovina il consiglio di HOLDLOCK è solo un bonus! – Justin

Problemi correlati