sql >> Database >  >> RDS >> Sqlserver

SQL MERGE-instructie om gegevens bij te werken

Ervan uitgaande dat u een echte SQL Server MERGE wilt verklaring:

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

Als u ook records in het doel wilt verwijderen die niet in de bron staan:

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;

Omdat dit een beetje populairder is geworden, heb ik het gevoel dat ik dit antwoord een beetje moet uitbreiden met enkele kanttekeningen om op te letten.

Ten eerste zijn er verschillende blogs die rapporteren over gelijktijdigheidsproblemen met de MERGE verklaring in oudere versies van SQL Server. Ik weet niet of dit probleem ooit is behandeld in latere edities. Hoe dan ook, dit kan grotendeels worden omzeild door de HOLDLOCK . op te geven of SERIALIZABLE vergrendel hint:

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

U kunt hetzelfde bereiken met strengere transactie-isolatieniveaus.

Er zijn verschillende andere bekende problemen met MERGE . (Merk op dat sinds Microsoft Connect nuked en problemen in het oude systeem niet koppelde aan problemen in het nieuwe systeem, deze oudere problemen moeilijk op te sporen zijn. Bedankt, Microsoft!) Van wat ik kan zien, zijn de meeste niet gebruikelijk problemen of kan worden omzeild met dezelfde vergrendelingstips als hierboven, maar ik heb ze niet getest.

Zoals het is, ook al heb ik nooit problemen gehad met de MERGE statement zelf, ik gebruik altijd de WITH (HOLDLOCK) hint nu, en ik gebruik de verklaring liever alleen in de meest eenvoudige gevallen.



  1. Oracle verwijdert rijen uit meerdere tabellen

  2. mysql REGEXP komt niet overeen

  3. Hoe NVL() werkt in MariaDB

  4. Mysql ERROR 1241 (21000):operand moet 1 kolom(men) bevatten