MERGE Violation de la contrainte PRIMARY KEY

J'ai une table de relation many-to-many SQL Server 2008 ( Assets ) avec deux colonnes:

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

Dans mon projet, je dois prendre des lignes de cette table, et les insert périodiquement dans une database répliquée. Donc, j'ai deux bases de données qui sont exactement les mêmes (contraintes incluses).

Pour "copyr" d'une database à l'autre, j'utilise une instruction MERGE avec une table temporaire. J'insère jusqu'à 50 loggings dans la table temporaire, puis fusionne la table temporaire avec la table Assets que je copy comme suit:

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

Cela fonctionne très bien, pour la plupart. Cependant, de time en time, j'ai l'erreur:

Violation de la contrainte PRIMARY KEY 'PK_Assets'. Impossible d'insert une key en double dans l'object 'dbo.Assets'. La valeur de la key en double est (dc5e3082-e2eb-4bdf-a640-94e0f59411ed, 22). La déclaration a été résiliée.

Quand je vérifie dans la table des Assets , aucun logging de ce type n'existe … alors je suis confus de savoir comment j'insertais une key en double.

Une idée de ce qui se passe ici?

METTRE À JOUR

Lors des tests, il fonctionne 6 fois avec succès, en insérant 300 lignes. Au 7ème essai, cela donne toujours la même erreur que ci-dessus. En outre, quand je INSERT (dc5e3082-e2eb-4bdf-a640-94e0f59411ed, 22) par lui-même, cela fonctionne bien. Mon test est alors capable de continuer et d'insert les lignes restantes sans erreurs.

Vous devez append une HOLDLOCK sur votre instruction MERGE . Essayez ce qui suit:

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

Cela évite la condition de concurrency dans laquelle vous vous trouvez. Voir plus d'info ici

MODIFIER

Sur la base de votre mise à jour, la seule autre chose que je peux penser est que votre table temporaire pourrait avoir un logging en double. Pouvez-vous vérifier?