Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

SQL MERGE-Anweisung zum Aktualisieren von Daten

Angenommen, Sie möchten einen tatsächlichen SQL Server MERGE Aussage:

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

Wenn Sie auch Datensätze im Ziel löschen möchten, die nicht in der Quelle sind:

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;

Da dies etwas populärer geworden ist, sollte ich diese Antwort ein wenig mit einigen Einschränkungen erweitern, die Sie beachten sollten.

Erstens gibt es mehrere Blogs, die über Parallelitätsprobleme mit MERGE Erklärung in älteren Versionen von SQL Server. Ich weiß nicht, ob dieses Problem jemals in späteren Ausgaben behandelt wurde. In jedem Fall kann dies größtenteils durch Angabe von HOLDLOCK umgangen werden oder SERIALIZABLE Sperrhinweis:

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

Sie können dasselbe auch mit restriktiveren Transaktionsisolationsstufen erreichen.

Es gibt mehrere andere bekannte Probleme mit MERGE . (Beachten Sie, dass, da Microsoft Connect vernichtet und Probleme im alten System nicht mit Problemen im neuen System verknüpft hat, diese älteren Probleme schwer aufzuspüren sind. Danke, Microsoft!) Soweit ich das beurteilen kann, sind die meisten von ihnen nicht üblich Probleme oder kann mit denselben Sperrhinweisen wie oben umgangen werden, aber ich habe sie nicht getestet.

So wie es ist, obwohl ich noch nie Probleme mit dem MERGE hatte -Anweisung selbst verwende ich immer die WITH (HOLDLOCK) Hinweis, und ich ziehe es vor, die Anweisung nur in den einfachsten Fällen zu verwenden.