sql >> Base de Datos >  >> RDS >> Sqlserver

Sentencia SQL MERGE para actualizar datos

Suponiendo que desea un SQL Server MERGE declaración:

MERGE INTO dbo.energydata WITH (HOLDLOCK) AS target
USING dbo.temp_energydata AS source
    ON target.webmeterID = source.webmeterID
    AND target.DateTime = source.DateTime
WHEN MATCHED THEN 
    UPDATE SET target.kWh = source.kWh
WHEN NOT MATCHED BY TARGET THEN
    INSERT (webmeterID, DateTime, kWh)
    VALUES (source.webmeterID, source.DateTime, source.kWh);

Si también desea eliminar registros en el destino que no están en el origen:

MERGE INTO dbo.energydata WITH (HOLDLOCK) AS target
USING dbo.temp_energydata AS source
    ON target.webmeterID = source.webmeterID
    AND target.DateTime = source.DateTime
WHEN MATCHED THEN 
    UPDATE SET target.kWh = source.kWh
WHEN NOT MATCHED BY TARGET THEN
    INSERT (webmeterID, DateTime, kWh)
    VALUES (source.webmeterID, source.DateTime, source.kWh)
WHEN NOT MATCHED BY SOURCE THEN
    DELETE;

Debido a que esto se ha vuelto un poco más popular, creo que debería ampliar un poco esta respuesta con algunas advertencias a tener en cuenta.

Primero, hay varios blogs que informan problemas de concurrencia con MERGE declaración en versiones anteriores de SQL Server. No sé si este problema se ha abordado alguna vez en ediciones posteriores. De cualquier manera, esto se puede solucionar en gran medida especificando HOLDLOCK o SERIALIZABLE sugerencia de bloqueo:

MERGE INTO dbo.energydata WITH (HOLDLOCK) AS target
[...]

También puede lograr lo mismo con niveles de aislamiento de transacciones más restrictivos.

Hay varios otros problemas conocidos con MERGE . (Tenga en cuenta que, dado que Microsoft eliminó Connect y no vinculó los problemas del sistema anterior con los problemas del sistema nuevo, estos problemas anteriores son difíciles de rastrear. ¡Gracias, Microsoft!) Por lo que puedo decir, la mayoría de ellos no son comunes problemas o se puede solucionar con las mismas sugerencias de bloqueo que las anteriores, pero no las he probado.

Tal como está, aunque nunca he tenido ningún problema con MERGE yo mismo, siempre uso WITH (HOLDLOCK) pista ahora, y prefiero usar la declaración solo en los casos más sencillos.