MERGE Befehl in T-SQL: Die Anleitung für effiziente Datenaktualisierung

Einleitung

In diesem Artikel lernst du, wie du den MERGE-Befehl in T-SQL einsetzen kannst, um komplexe Datenoperationen mit hoher Effizienz durchzuführen. Wir verwenden dabei die AdventureWorks-Datenbank, um dir praxisnahe Beispiele zu zeigen. Der MERGE-Befehl ist besonders nützlich, wenn du aus einer Quelltabelle Daten in eine Zieltabelle einfügen, aktualisieren oder löschen willst – alles in einem einzigen Befehl.


Was ist der MERGE-Befehl?

Der MERGE-Befehl ist ein mächtiges Feature in T-SQL, das es dir erlaubt, Datensätze aus einer Quell-Tabelle basierend auf bestimmten Kriterien in eine Zieltabelle einzufügen, zu aktualisieren oder zu löschen. Er ermöglicht es, komplexe Synchronisationsvorgänge mit nur einem Befehl durchzuführen – ohne mehrere INSERT-, UPDATE- und DELETE-Anweisungen schreiben zu müssen.


Voraussetzungen

Bevor wir beginnen, musst du sicherstellen, dass du Zugriff auf die AdventureWorks-Datenbank hast. Falls du sie noch nicht installiert hast, kannst du sie von Microsoft herunterladen (https://github.com/microsoft/sql-server-samples/releases/tag/adventureworks).


Grundlegende Syntax des MERGE-Befehls

sqlMERGE [ZielTabelle] AS Ziel
USING [QuellTabelle] AS Quelle
ON (Bedingung)
WHEN MATCHED THEN
    UPDATE SET Spalte1 = Wert1, ...
WHEN NOT MATCHED BY TARGET THEN
    INSERT (Spalte1, Spalte2, ...)
    VALUES (Wert1, Wert2, ...)
WHEN NOT MATCHED BY SOURCE THEN
    DELETE;

Die verschiedenen Teile des Befehls sind:

  • MERGE: Startet den Befehl.
  • AS Ziel / AS Quelle: Alias für die Zielspalte und die Quelltabelle.
  • ON (Bedingung): Gibt an, wie die Datensätze miteinander verglichen werden (z. B. Ziel.ID = Quelle.ID).
  • WHEN MATCHED THEN UPDATE: Aktualisiert einen Datensatz, wenn er bereits in der Ziel-Tabelle existiert.
  • WHEN NOT MATCHED BY TARGET THEN INSERT: Fügt einen Datensatz ein, wenn er nicht in der Ziel-Tabelle existiert.
  • WHEN NOT MATCHED BY SOURCE THEN DELETE: Löscht einen Datensatz aus der Ziel-Tabelle, wenn er in der Quelle nicht mehr vorhanden ist.

Beispiel 1: Grundlegende MERGE-Operation

Nehmen wir an, du möchtest eine Tabelle SalesLT.CustomerUpdate erstellen, die Kundeninformationen aus der Tabelle SalesLT.Customer aktualisiert und ergänzt. Wir wollen den Befehl so aufbauen, dass:

  • Wenn ein Kunde in SalesLT.Customer bereits existiert, wird er aktualisiert.
  • Wenn ein Kunde nicht existiert, wird er eingefügt.
  • Wenn ein Kunde in der Quelle nicht mehr existiert, wird er gelöscht.

1: Erstelle die Ziel-Tabelle

IF OBJECT_ID('SalesLT.CustomerUpdate', 'U') IS NOT NULL
DROP TABLE SalesLT.CustomerUpdate;

CREATE TABLE SalesLT.CustomerUpdate (
CustomerID INT PRIMARY KEY,
NameStyle BIT,
Title NVARCHAR(8),
FirstName NVARCHAR(50),
MiddleName NVARCHAR(50),
LastName NVARCHAR(50),
Suffix NVARCHAR(10),
CompanyName NVARCHAR(128),
SalesPerson NVARCHAR(256),
EmailAddress NVARCHAR(50),
Phone NVARCHAR(25),
PasswordHash NVARCHAR(128),
PasswordSalt NVARCHAR(10),
rowguid UNIQUEIDENTIFIER,
ModifiedDate DATETIME
);

2: Füge Daten in die Ziel-Tabelle ein

INSERT INTO SalesLT.CustomerUpdate (CustomerID, NameStyle, Title, FirstName, MiddleName, LastName, Suffix, CompanyName, SalesPerson, EmailAddress, Phone, PasswordHash, PasswordSalt, rowguid, ModifiedDate)
SELECT CustomerID, NameStyle, Title, FirstName, MiddleName, LastName, Suffix, CompanyName, SalesPerson, EmailAddress, Phone, PasswordHash, PasswordSalt, rowguid, ModifiedDate
FROM SalesLT.Customer;

3: Erstelle eine Testquelle

-- Erstelle eine temporäre Tabelle als Quelle für unsere Tests
IF OBJECT_ID('tempdb..#CustomerSource', 'U') IS NOT NULL
DROP TABLE #CustomerSource;

CREATE TABLE #CustomerSource (
CustomerID INT,
FirstName NVARCHAR(50),
LastName NVARCHAR(50),
EmailAddress NVARCHAR(50),
CompanyName NVARCHAR(128)
);

INSERT INTO #CustomerSource VALUES
(1, 'John', 'Doe', 'john.doe@example.com', 'ABC Corp'),
(2, 'Jane', 'Smith', 'jane.smith@example.com', 'XYZ Ltd'),
(3, 'Bob', 'Johnson', 'bob.johnson@example.com', 'DEF Inc');

4: Führe den MERGE-Befehl aus

MERGE SalesLT.CustomerUpdate AS Ziel
USING #CustomerSource AS Quelle
ON (Ziel.CustomerID = Quelle.CustomerID)
WHEN MATCHED THEN
UPDATE SET
FirstName = Quelle.FirstName,
LastName = Quelle.LastName,
EmailAddress = Quelle.EmailAddress,
CompanyName = Quelle.CompanyName
WHEN NOT MATCHED BY TARGET THEN
INSERT (CustomerID, NameStyle, Title, FirstName, MiddleName, LastName, Suffix, CompanyName, SalesPerson, EmailAddress, Phone, PasswordHash, PasswordSalt, rowguid, ModifiedDate)
VALUES (Quelle.CustomerID, 0, NULL, Quelle.FirstName, NULL, Quelle.LastName, NULL, Quelle.CompanyName, NULL, Quelle.EmailAddress, NULL, NULL, NULL, NEWID(), GETDATE());

Beispiel 2: MERGE mit DELETE-Operation

Jetzt wollen wir den Befehl so erweitern, dass auch gelöschte Datensätze aus der Ziel-Tabelle entfernt werden.

Erstelle eine neue Quell-Tabelle

IF OBJECT_ID('tempdb..#CustomerSource2', 'U') IS NOT NULL
DROP TABLE #CustomerSource2;

CREATE TABLE #CustomerSource2 (
CustomerID INT,
FirstName NVARCHAR(50),
LastName NVARCHAR(50),
EmailAddress NVARCHAR(50),
CompanyName NVARCHAR(128)
);

INSERT INTO #CustomerSource2 VALUES
(1, 'John', 'Doe', 'john.doe@example.com', 'ABC Corp'),
(2, 'Jane', 'Smith', 'jane.smith@example.com', 'XYZ Ltd');

MERGE mit DELETE

MERGE SalesLT.CustomerUpdate AS Ziel
USING #CustomerSource2 AS Quelle
ON (Ziel.CustomerID = Quelle.CustomerID)
WHEN MATCHED THEN
UPDATE SET
FirstName = Quelle.FirstName,
LastName = Quelle.LastName,
EmailAddress = Quelle.EmailAddress,
CompanyName = Quelle.CompanyName
WHEN NOT MATCHED BY TARGET THEN
INSERT (CustomerID, NameStyle, Title, FirstName, MiddleName, LastName, Suffix, CompanyName, SalesPerson, EmailAddress, Phone, PasswordHash, PasswordSalt, rowguid, ModifiedDate)
VALUES (Quelle.CustomerID, 0, NULL, Quelle.FirstName, NULL, Quelle.LastName, NULL, Quelle.CompanyName, NULL, Quelle.EmailAddress, NULL, NULL, NULL, NEWID(), GETDATE())
WHEN NOT MATCHED BY SOURCE THEN
DELETE;

Vorteile des MERGE-Befehls

  1. Effizienz: Einzelner Befehl statt mehrerer INSERTUPDATE und DELETE.
  2. Atomicität: Die Operation wird als ein atomarer Vorgang ausgeführt – entweder alles gelingt oder nichts.
  3. Konsistenz: Verhindert Inkonsistenzen durch parallele Änderungen.
  4. Performance: Weniger Roundtrips zum Server, was besonders bei großen Datensätzen von Vorteil ist.

Nachteile und Einschränkungen

  1. Komplexität: Für Anfänger kann der MERGE-Befehl schwer zu verstehen sein.
  2. Fehlerbehandlung: Fehlermeldungen können unklar sein, wenn etwas schiefgeht.
  3. Leistung bei sehr großen Datenmengen: Bei extrem großen Tabellen kann es langsamer sein als separate Operationen.

Best Practices

  1. Verwende immer eine klare ON-Bedingung, um sicherzustellen, dass die richtigen Datensätze verglichen werden.
  2. Teste den MERGE-Befehl mit einer SELECT-Anweisung vor der eigentlichen Ausführung.
  3. Verwende Transaktionen, um sicherzustellen, dass Änderungen rückgängig gemacht werden können.
  4. Vermeide komplexe Logik in WHEN-Klauseln, um die Lesbarkeit zu verbessern.

Fazit

Der MERGE-Befehl ist ein leistungsstarkes und effizientes Tool zur Synchronisation von Daten in SQL Server. Mit ihm kannst du komplexe Update-, Insert- und Delete-Vorgänge in nur einem Befehl durchführen. Wenn du regelmäßig mit großen Datensätzen arbeitest, lohnt sich die Einarbeitung in den MERGE-Befehl – er spart Zeit, verbessert die Performance und reduziert Fehlerquellen.