Viele Leute werden Ihnen vorschlagen, die MERGE
aber ich warne Sie davor. Standardmäßig schützt es Sie nicht vor Gleichzeitigkeit und Race Conditions, genauso wenig wie mehrere Anweisungen, und es birgt andere Gefahren:
Selbst mit dieser "einfacheren" Syntax bevorzuge ich immer noch diesen Ansatz (Fehlerbehandlung der Kürze halber weggelassen):
BEGIN TRANSACTION;
UPDATE dbo.table WITH (UPDLOCK, SERIALIZABLE)
SET ... WHERE PK = @PK;
IF @@ROWCOUNT = 0
BEGIN
INSERT dbo.table(PK, ...) SELECT @PK, ...;
END
COMMIT TRANSACTION;
Viele Leute werden diesen Weg vorschlagen:
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;
Dies führt jedoch nur dazu, dass Sie die Tabelle möglicherweise zweimal lesen müssen, um die zu aktualisierende(n) Zeile(n) zu finden. Im ersten Beispiel brauchen Sie die Zeile(n) nur einmal zu suchen. (In beiden Fällen wird eine Einfügung vorgenommen, wenn beim ersten Lesen keine Zeile gefunden wird).
Andere werden diesen Weg vorschlagen:
BEGIN TRY
INSERT ...
END TRY
BEGIN CATCH
IF ERROR_NUMBER() = 2627
UPDATE ...
END CATCH
Dies ist jedoch problematisch, und zwar aus keinem anderen Grund als dem, dass es viel teurer ist, SQL Server Ausnahmen abfangen zu lassen, die Sie von vornherein hätten verhindern können, außer in dem seltenen Fall, dass fast jede Einfügung fehlschlägt. Ich beweise dies hier:
2 Stimmen
Ähnliche Fragen: * Stored Proc einfügen aktualisieren auf SQL Server * SQL Server 2005-Implementierung von MySQL REPLACE INTO?
53 Stimmen
Für alle, die diese Frage zum ersten Mal stellen - bitte lesen Sie unbedingt alle Antworten und Kommentare. Das Alter kann manchmal zu irreführenden Informationen führen...
1 Stimmen
Erwägen Sie die Verwendung des EXCEPT-Operators, der in SQL Server 2005 eingeführt wurde.