sql >> Databasteknik >  >> RDS >> Sqlserver

UPPDATERA om det finns annat INSERT i SQL Server 2008

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.




  1. Hur COS() fungerar i MariaDB

  2. Exportera Oracle Table till Excel-kalkylblad

  3. Hur du hanterar din databas med Adminer

  4. Dynamisk Oracle Pivot_In_Clause