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.