sql >> Databáze >  >> RDS >> Sqlserver

AKTUALIZUJTE, pokud existuje jinak INSERT v SQL Server 2008

Mnoho lidí vám navrhne, abyste použili MERGE , ale varuji vás před tím. Ve výchozím nastavení vás nechrání před souběžnými a rasovými podmínkami o nic víc než několik příkazů, ale přináší další nebezpečí:

  • Používejte opatrně s příkazem MERGE serveru SQL Server
  • Čemu se vyvarovat, pokud chcete použít MERGE
  • Vzory a antivzory UPSERT serveru SQL Server

I když je k dispozici tato "jednodušší" syntaxe, stále preferuji tento přístup (pro stručnost vynecháno zpracování chyb):

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;

Více informací o tomto UPSERT přístup zde:

  • Přestaňte prosím používat tento anti-vzor UPSERT

Mnoho lidí navrhne tento způsob:

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;

To vše však zajišťuje, že budete možná muset přečíst tabulku dvakrát, abyste našli řádek (řádky), které mají být aktualizovány. V prvním příkladu budete potřebovat najít řádek(y) pouze jednou. (V obou případech, pokud nejsou nalezeny žádné řádky z počátečního čtení, dojde k vložení.)

Ostatní navrhnou tento způsob:

BEGIN TRY
  INSERT ...
END TRY
BEGIN CATCH
  IF ERROR_NUMBER() = 2627
    UPDATE ...
END CATCH

To je však problematické, pokud z žádného jiného důvodu, než že ponechání SQL Serveru zachytit výjimky, kterým jste mohli předejít, je mnohem dražší, s výjimkou výjimečného scénáře, kdy selže téměř každý insert. Dokazuji to zde:

  • Před vstupem do TRY/CATCH zkontrolujte potenciální porušení omezení
  • Vliv různých technik zpracování chyb na výkon

Nejste si jisti, co si myslíte, že získáte jediným prohlášením; Myslím, že tím nic nezískáš. MERGE je jediný příkaz, ale stejně musí skutečně provádět více operací – i když si myslíte, že tomu tak není.




  1. Jak zkrátit tabulku v postupu Oracle?

  2. Mohu čárkou oddělit více řádků do jednoho sloupce?

  3. PostgreSQL vrátí funkci s uživatelským typem dat

  4. Pořadí Mysql podle konkrétních hodnot ID