2016-07-06 5 views
3

Angenommen, eine Tabellenstruktur von MyTable (MyTableId NVARCHAR (MAX) PRIMARY KEY, NumberOfInserts INTEGER).Sichere Lösungen für INSERT oder UPDATE auf SQL Server 2016

Ich brauche oft entweder aktualisieren das heißt einen Zähler von einem vorhandenen Datensatz erhöhen oder einen neuen Datensatz einfügen, wenn es nicht mit einem Wert von 0 für NumberOfInserts existiert.

Im Wesentlichen:

IF (MyTableId exists) 
    run UPDATE command 
ELSE 
    run INSERT command 

Meine Sorge ist, Bedingungen Daten aufgrund von Rasse, usw.

Was ist der sicherste Weg, dies zu schreiben, zu verlieren?

Ich brauche es 100% genau, wenn möglich zu sein und bereit Geschwindigkeit zu opfern, wo nötig.

+0

Sie könnten prüfen, mit dem Befehl MERGE, kombinierte Update, einfügen und löschen alle auf einmal. Paar von Beobachtungen, bitte nicht diese Spalte 'Schlüssel' nennen es ist ein reserviertes Wort in SQL Server. Verwenden Sie das auch als Ihren Primärschlüssel? Wenn das so ist, ist NVARCHAR (MAX) eine wirklich schlechte Idee. –

Antwort

4

MERGE Anweisung kann sowohl UPDATE als auch INSERT (und DELETE, falls erforderlich) ausführen.

Auch wenn es eine einzige atomare Aussage ist, ist es wichtig, HOLDLOCK Abfragehinweis zu verwenden Race-Bedingung zu verhindern. Es gibt einen Blog-Post “UPSERT” Race Condition With MERGE von Dan Guzman, wo er in großen Details erklärt, wie es funktioniert und ein Testskript zur Verfügung stellt, um es zu verifizieren.

Die Abfrage selbst ist straight-forward:

DECLARE @NewKey NVARCHAR(MAX) = ...; 

MERGE INTO dbo.MyTable WITH (HOLDLOCK) AS Dst 
USING 
(
    SELECT @NewKey AS NewKey 
) AS Src 
ON Src.NewKey = Dst.[Key] 
WHEN MATCHED THEN 
UPDATE 
SET NumberOfInserts = NumberOfInserts + 1 
WHEN NOT MATCHED THEN 
INSERT 
(
    [Key] 
    ,NumberOfInserts 
) 
VALUES 
(
    @NewKey 
    ,0 
); 

Natürlich können Sie auch explizit zweistufigen Ansatz mit einem separaten Check verwenden, wenn eine Zeile vorhanden ist und eine separate UPDATE und INSERT Aussagen. Stellen Sie sicher, dass Sie alle in eine Transaktion mit entsprechenden Tabellensperrhinweisen einbetten.

Siehe Conditional INSERT/UPDATE Race Condition von Dan Guzman für weitere Einzelheiten.

+0

vorsichtig verwenden MERGE ... es gibt eine Tonne Probleme mit ihm: https://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/ –