Veel mensen zullen je aanraden om MERGE
te gebruiken , maar ik waarschuw u ervoor. Standaard beschermt het je niet tegen gelijktijdigheid en race-omstandigheden, net zo min als meerdere verklaringen, maar het introduceert wel andere gevaren:
- Wees voorzichtig met de MERGE-instructie van SQL Server
- Wat u moet vermijden als u MERGE wilt gebruiken
- SQL Server UPSERT-patronen en antipatronen
Zelfs met deze "eenvoudigere" syntaxis die beschikbaar is, geef ik nog steeds de voorkeur aan deze benadering (foutafhandeling weggelaten voor de beknoptheid):
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
UPDATE dbo.table SET ... WHERE PK = @PK;
IF @@ROWCOUNT = 0
BEGIN
INSERT dbo.table(PK, ...) SELECT @PK, ...;
END
COMMIT TRANSACTION;
Meer info over deze UPSERT
benader hier:
- Stop met het gebruik van dit UPSERT-antipatroon
Veel mensen zullen dit op deze manier voorstellen:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
IF EXISTS (SELECT 1 FROM dbo.table WHERE PK = @PK)
BEGIN
UPDATE ...
END
ELSE
BEGIN
INSERT ...
END
COMMIT TRANSACTION;
Maar dit alles zorgt ervoor dat u de tabel mogelijk twee keer moet lezen om de rij(en) te vinden die moeten worden bijgewerkt. In het eerste voorbeeld hoeft u de rij(en) maar één keer te zoeken. (In beide gevallen, als er geen rijen worden gevonden vanaf de eerste lezing, vindt er een invoeging plaats.)
Anderen zullen het op deze manier voorstellen:
BEGIN TRY
INSERT ...
END TRY
BEGIN CATCH
IF ERROR_NUMBER() = 2627
UPDATE ...
END CATCH
Dit is echter problematisch als het om geen andere reden dan het toestaan dat SQL Server uitzonderingen opvangt die u in de eerste plaats had kunnen voorkomen, veel duurder is, behalve in het zeldzame scenario waarin bijna elke invoeging mislukt. Dat bewijs ik hier:
- Controleren op mogelijke schendingen van beperkingen voordat TRY/CATCH wordt ingevoerd
- Prestatie-impact van verschillende technieken voor foutafhandeling
Niet zeker wat u denkt te winnen door een enkele verklaring te hebben; Ik denk dat je er niets mee wint. MERGE
is een enkele instructie, maar het moet toch echt meerdere bewerkingen uitvoeren - ook al doet u denken dat dit niet het geval is.