sql >> Database teknologi >  >> RDS >> Sqlserver

SQL MERGE-sætning for at opdatere data

Forudsat at du ønsker en faktisk SQL-server MERGE erklæring:

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

Hvis du også vil slette poster i målet, der ikke er i kilden:

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;

Fordi dette er blevet lidt mere populært, føler jeg, at jeg bør udvide dette svar lidt med nogle forbehold, som jeg skal være opmærksom på.

For det første er der adskillige blogs, som rapporterer samtidighedsproblemer med MERGE erklæring i ældre versioner af SQL Server. Jeg ved ikke, om dette problem nogensinde er blevet behandlet i senere udgaver. Uanset hvad, kan dette stort set løses ved at angive HOLDLOCK eller SERIALIZABLE låsetip:

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

Du kan også opnå det samme med mere restriktive transaktionsisoleringsniveauer.

Der er adskillige andre kendte problemer a> med MERGE . (Bemærk, at siden Microsoft nuked Connect og ikke linkede problemer i det gamle system til problemer i det nye system, er disse ældre problemer svære at spore. Tak, Microsoft!) Så vidt jeg kan se, er de fleste af dem ikke almindelige problemer eller kan løses med de samme låsetip som ovenfor, men jeg har ikke testet dem.

Som det er, selvom jeg aldrig har haft problemer med MERGE selv, bruger jeg altid WITH (HOLDLOCK) tip nu, og jeg foretrækker kun at bruge udsagnet i de mest ligetil tilfælde.



  1. Generer en tilfældig alfanumerisk streng som en primær nøgle til en model

  2. MySQL char vs. int

  3. Hvordan indlæses et stort antal strenge for at matche med Oracle-databasen?

  4. Brug af vælg i lokal variabel og forberedt erklæring i mysql