sql >> Database >  >> RDS >> Sqlserver

UPDATE indien bestaat anders INSERT in SQL Server 2008

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.




  1. Hoe pgBackRest te gebruiken om een ​​back-up te maken van PostgreSQL en TimescaleDB

  2. Maximum aantal records in een MySQL-databasetabel

  3. MySQLDumper:een op PHP en Perl gebaseerde MySQL-databaseback-uptool

  4. Hoe geneste matrices in een postgres json-kolom opvragen?