Många kommer att föreslå att du använder MERGE
, men jag varnar dig för det. Som standard skyddar det dig inte från samtidiga och tävlingsförhållanden mer än flera uttalanden, men det introducerar andra faror:
- Var försiktig med SQL Servers MERGE-uttalande
- Vad du ska undvika om du vill använda MERGE
- SQL Server UPSERT-mönster och antimönster
Även med denna "enklare" syntax tillgänglig, föredrar jag fortfarande detta tillvägagångssätt (felhantering utelämnas för korthetens skull):
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;
Mer information om denna UPSERT
närma dig här:
- Snälla sluta använda detta UPSERT-antimönster
Många kommer att föreslå det här sättet:
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;
Men allt detta åstadkommer är att se till att du kan behöva läsa tabellen två gånger för att hitta raden/raderna som ska uppdateras. I det första provet behöver du bara hitta raden/raderna en gång. (I båda fallen, om inga rader hittas från den första läsningen, sker en infogning.)
Andra föreslår så här:
BEGIN TRY
INSERT ...
END TRY
BEGIN CATCH
IF ERROR_NUMBER() = 2627
UPDATE ...
END CATCH
Detta är dock problematiskt om det inte av någon annan anledning än att låta SQL Server fånga undantag som du kunde ha förhindrat i första hand är mycket dyrare, förutom i det sällsynta scenariot där nästan varje insättning misslyckas. Jag bevisar lika mycket här:
- Kontrollerar efter potentiella överträdelser av begränsningar innan du går in i TRY/CATCH
- Prestandan påverkan av olika felhanteringstekniker
Inte säker på vad du tror att du vinner på att ha ett enda påstående; Jag tror inte du vinner något. MERGE
är ett enda påstående men det måste fortfarande verkligen utföra flera operationer ändå - även om det får dig att tro att det inte gör det.