2010-07-26 17 views
9

Estoy utilizando SQL Server 2008, y me gustaría ser capaz de tomar ventaja de algo así como EN DUPLICATE KEY UPDATE cláusula de MySQL para INSERT declaracionesposible simular la funcionalidad de MySQL en DUPLICATE KEY UPDATE con SQL Server

código heredado actual hace un borrado, y la posterior inserción que se está ejecutando en problemas de concurrencia con inserciones de clave duplicados de hilos separados:

Aquí está el error que veo en mi entorno de producción:

Violation of PRIMARY KEY constraint 'PK_Audience'. Cannot insert duplicate key in object 'dbo.Audience'. 

(sp_ContentUpdate)

Clave principal:

AudienceId, VersionId 

Offending SQL:

DELETE FROM dbo.Audience 
WHERE VersionId = @VersionId 

IF @AudienceXml IS NOT NULL 
    BEGIN 
    INSERT INTO dbo.Audience (
     VersionId, 
     AudienceId, 
     CreatedDate, 
     CreatedByPersonId, 
     ) 
    SELECT @VersionId, 
      AudienceId, 
      GETUTCDATE(), 
      @PersonId 
       FROM dbo.Audience 
    JOIN @AudienceXml.nodes('/Audiences/Audience') node(c) 
    ON  Audience.AudienceName = c.value('@Name', 'nvarchar(50)') 
    END 

envolver este TSQL en una transacción parece bien eliminar el problema de concurrencia o enmascarar el problema cambiando los tiempos. Sin embargo, no creo que el ajuste en una transacción haya resuelto la concurrencia.

Quizás estoy haciendo esto mal. Tus sugerencias son apreciadas.

+0

posible duplicado de [¿El SQL Server ofrece nada que se extienden sobre DUPLICATE KEY UPDATE de MySQL] (http: // stackoverflow .com/questions/1197733/does-sql-server-offer-anything-like-mysqls-on-duplicate-key-update) –

Respuesta

10

Bueno, Bill nos ganó todo, pero aquí es una muestra de lo que podría ser:

Merge dbo.Audience As target 
Using (
     Select @VersionId As VersionId, AudienceId, GetUtcDate() As CreatedDate, @PersonId As CreatedByPersonId 
     From dbo.Audience 
      Join @AudienceXml.nodes('/Audiences/Audience') node(c) 
       On Audience.AudienceName = c.value('@Name', 'nvarchar(50)') 
     ) 
When Matched Then 
    Update 
    Set VersoinId = target.VersionId, Audience = target.AudienceId 
     , CreatedDate = target.CreatedDate 
     , CreatedByPersionId = target.CreatedByPersonId 
When Not Matched Then 
    Insert dbo.Audience(VersionId, AudienceId, CreatedDate, CreatedByPersonId) 
+1

+1 Saludos por el ejemplo, Thomas. –

+0

+1 Guau, gracias por hacer el trabajo. –

+1

@Bill Karwin - Thx. Cuando respondiste, me sentí como el personaje de Rusty cuando intenta reclutar a Saul en Ocean's 11. "Thomas, vi la respuesta antes de levantarte esta mañana". Pero, los puntos de brownie por un poco de trabajo extra también son buenos. :) – Thomas

8

Debería leer acerca de cómo usar la declaración MERGE en Microsoft SQL Server 2008. Esta es en realidad la forma ANSI/ISO SQL de manejar esta situación (MySQL ON DUPLICATE KEY es un MySQL de propiedad).

Consulte los documentos en el MERGE statement en MSDN.

+1

+1: Drats, pásame. –

Cuestiones relacionadas