sql >> Databasteknik >  >> RDS >> Sqlserver

SQL MERGE-sats för att uppdatera data

Förutsatt att du vill ha en verklig SQL-server MERGE uttalande:

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

Om du också vill ta bort poster i målet som inte finns i källan:

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;

Eftersom det här har blivit lite mer populärt känner jag att jag borde utöka det här svaret lite med några varningar att vara medveten om.

För det första finns det flera bloggar som rapporterar samtidighetsproblem med MERGE uttalande i äldre versioner av SQL Server. Jag vet inte om denna fråga någonsin har behandlats i senare upplagor. Hur som helst kan detta till stor del lösas genom att specificera HOLDLOCK eller SERIALIZABLE låstips:

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

Du kan också åstadkomma samma sak med mer restriktiva transaktionsisoleringsnivåer.

Det finns flera andra kända problem med MERGE . (Observera att eftersom Microsoft nuked Connect och inte länkade problem i det gamla systemet till problem i det nya systemet, är dessa äldre problem svåra att spåra. Tack, Microsoft!) Vad jag kan säga är de flesta av dem inte vanliga problem eller kan lösas med samma låstips som ovan, men jag har inte testat dem.

Som det är, även om jag aldrig har haft några problem med MERGE själv använder jag alltid WITH (HOLDLOCK) tips nu, och jag föredrar att använda påståendet endast i de mest enkla fallen.



  1. Hur inkluderar man saknad data för flera grupperingar inom tidsperioden?

  2. PDO-motsvarigheten till mysql_num_rows eller mssql_num_rows

  3. array för multipla where_in-villkor i codeigniter

  4. utlösa SOLR-uppdatering efter MySQL-uppdatering