DBAtlas · Atlas für Datenbankbetrieb

MERGE / UPSERT (aktualisieren, falls vorhanden, sonst einfügen)

Oracle

MERGE INTO customer m
USING (SELECT 1 AS id, 'Ali' AS name, 500 AS balance FROM dual) k
ON (m.id = k.id)
WHEN MATCHED THEN
  UPDATE SET m.name = k.name, m.balance = k.balance
WHEN NOT MATCHED THEN
  INSERT (id, name, balance) VALUES (k.id, k.name, k.balance);

MERGE (Upsert) gleicht eine Quelle mit einem Ziel ab, aktualisiert passende Zeilen und fügt nicht passende ein; ideal für die Massensynchronisation von Daten. Oracle bietet starke MERGE-Unterstützung: Auch WHEN MATCHED ... DELETE und bedingte Updates sind möglich. Für eine einzeilige Quelle wird die Tabelle dual genutzt.

PostgreSQL

-- The PostgreSQL way: INSERT ... ON CONFLICT
INSERT INTO customer (id, name, balance)
VALUES (1, 'Ali', 500)
ON CONFLICT (id) DO UPDATE
  SET name = EXCLUDED.name, balance = EXCLUDED.balance;

Der klassische Upsert in PostgreSQL ist INSERT ... ON CONFLICT (unique column) DO UPDATE / DO NOTHING; auf die neuen Werte der kollidierenden Zeile greifst du über den Alias EXCLUDED zu. Seit PostgreSQL 15 wird auch die Standardanweisung MERGE unterstützt. ON CONFLICT ist auf einer einzelnen Tabelle atomar und weit verbreitet.

MySQL

INSERT INTO customer (id, name, balance)
VALUES (1, 'Ali', 500)
ON DUPLICATE KEY UPDATE
  name = VALUES(name), balance = VALUES(balance);

MySQL/MariaDB nutzen für Upserts INSERT ... ON DUPLICATE KEY UPDATE; kollidiert ein Unique- oder Primärschlüssel, wird die Zeile aktualisiert. Auf neue Werte greifst du mit VALUES(my_column) zu (oder ab 8.0.19 mit dem Zeilenalias 'new.my_column'). INSERT IGNORE überspringt die Zeile bei einem Konflikt stillschweigend. MySQL hat kein Standard-MERGE.

SQL Server

MERGE INTO customer AS m
USING (VALUES (1, 'Ali', 500)) AS k(id, name, balance)
ON m.id = k.id
WHEN MATCHED THEN
  UPDATE SET m.name = k.name, m.balance = k.balance
WHEN NOT MATCHED THEN
  INSERT (id, name, balance) VALUES (k.id, k.name, k.balance);

SQL Server unterstützt die Anweisung MERGE seit 2008; sie bietet zusätzliche Zweige wie WHEN NOT MATCHED BY SOURCE zum Löschen überzähliger Zeilen im Ziel. Eine MERGE-Anweisung muss mit einem Semikolon abgeschlossen werden. Hinweis: Wegen einiger Bugs in Randfällen werden für einfache Upserts mitunter separate INSERT-/UPDATE-Anweisungen bevorzugt.

MongoDB

// Find-and-update or insert with upsert:true
db.customer.updateOne(
  { id: 1 },
  { $set: { name: "Ali", balance: 500 } },
  { upsert: true }
)

In MongoDB ist Upsert eine native Option: Wird { upsert: true } zu updateOne/updateMany/findOneAndUpdate hinzugefügt, wird ein passendes Dokument aktualisiert, andernfalls ein neues angelegt. Für Massensynchronisation kommt die Aggregation-Stage $merge (Schreiben/Aktualisieren in eine Ziel-Collection) SQL-MERGE näher.

Redis

# SET is a natural upsert: it overwrites the key if present, otherwise creates it.
SET customer:1 '{"name":"Ali","balance":500}'
# Update/add a hash field:
HSET customer:1 name Ali balance 500

In Redis sind Schreibbefehle von Natur aus Upserts: SET/HSET aktualisieren den Schlüssel oder das Feld, falls vorhanden, sonst legen sie es an. Mit der Option SET ... NX schreibst du nur, wenn nicht vorhanden, mit XX nur, wenn vorhanden. Die Unterscheidung 'aktualisieren, falls vorhanden, sonst einfügen' ist bei den meisten Befehlen bereits das Standardverhalten.

Elasticsearch

# An index call with a document id acts like an upsert (replaces if present):
PUT customer/_doc/1
{ "name": "Ali", "balance": 500 }
# Partial update + insert if absent:
POST customer/_update/1
{ "doc": { "balance": 500 }, "doc_as_upsert": true }

In Elasticsearch ersetzt ein index-Aufruf (PUT) mit derselben _id das Dokument vollständig, falls vorhanden, sonst legt er es an (upsert-ähnlich). Für Teilaktualisierungen mit Einfügen bei Nichtvorhandensein nutze 'doc_as_upsert': true oder einen 'upsert'-Block in der _update API. Auch Scripted Upserts sind möglich.

In DBAtlas öffnen →