Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Instrução SQL MERGE para atualizar dados


Supondo que você queira um SQL Server MERGE real declaração:
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);

Se você também deseja excluir registros no destino que não estão na origem:
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;

Como isso se tornou um pouco mais popular, sinto que devo expandir esta resposta um pouco com algumas ressalvas a serem observadas.

Primeiro, existem vários blogs que relatam problemas de simultaneidade com o MERGE declaração em versões mais antigas do SQL Server. Não sei se esta questão já foi abordada em edições posteriores. De qualquer forma, isso pode ser amplamente contornado especificando o HOLDLOCK ou SERIALIZABLE dica de bloqueio:
MERGE INTO dbo.energydata WITH (HOLDLOCK) AS target
[...]

Você também pode fazer a mesma coisa com níveis de isolamento de transação mais restritivos.

Existem vários outros problemas conhecidos com MERGE . (Observe que, como a Microsoft desativou o Connect e não vinculou problemas no sistema antigo a problemas no novo sistema, esses problemas mais antigos são difíceis de rastrear. Obrigado, Microsoft!) Pelo que posso dizer, a maioria deles não é comum problemas ou pode ser contornado com as mesmas dicas de bloqueio acima, mas não as testei.

Como está, mesmo que eu nunca tenha tido problemas com o MERGE declaração, eu sempre uso o WITH (HOLDLOCK) dica agora, e prefiro usar a declaração apenas nos casos mais diretos.