2012-05-23 19 views
6

que tiene un SQL Server 2008 muchos-a-muchos tabla de relación (Assets) con dos columnas:MERGE Violación de restricción PRIMARY KEY

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

en mi proyecto, tengo que tomar filas de esta tabla, y insertarlos en una base de datos replicada periódicamente. Entonces, tengo dos bases de datos que son exactamente iguales (restricciones incluidas).

Para "copiar" de una base de datos a otra, utilizo una instrucción MERGE con una tabla temporal. Insertar hasta 50 registros en la tabla temporal, y luego fusionar la tabla temporal con la tabla Assets estoy copiando en la siguiente forma:

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

Esto funciona muy bien, en su mayor parte. Sin embargo, de vez en cuando, me sale el error:

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.

Cuando compruebo en la tabla Assets, no existe tal registro ... así que estoy confundido cómo iba a ser la inserción de una llave duplicada.

¿Alguna idea de lo que está pasando aquí?

ACTUALIZACIÓN

Cuando la prueba, se ejecuta con éxito 6 veces, la inserción de 300 filas. En el 7mo intento, siempre da el mismo error que se muestra arriba. Además, cuando yo INSERT(dc5e3082-e2eb-4bdf-a640-94e0f59411ed, 22) por sí mismo, funciona bien. Mi prueba luego puede continuar e insertar las filas restantes sin errores.

+0

La declaración de fusión es conocida por tener errores. Quizás tocas uno. Por favor, publique el plan de ejecución. – usr

Respuesta

12

Necesita agregar un HOLDLOCK en su declaración MERGE. Pruebe lo siguiente:

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

Esto evita la condición de carrera en la que se está encontrando. Ver más información here

EDITAR

En base a su actualización, la única otra cosa que puedo pensar es que su tabla temporal podría tener un registro duplicado en el mismo. ¿Puedes verificarlo?

+0

Gracias por la respuesta rápida. Probablemente me salvaste a mí (y a otros) algunos dolores de cabeza en el futuro, pero desafortunadamente esto no solucionó mi problema. Por favor mira la pregunta actualizada – Justin

+2

Usted es 100% correcto. Tenía un duplicado en mi mesa temporal. ¡Adivina el consejo de HOLDLOCK es solo una bonificación! – Justin

Cuestiones relacionadas