MERGE / UPSERT (update if exists, else insert)
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) matches a source against a target, updating matching rows and inserting non-matching ones; ideal for bulk data synchronization. Oracle has strong MERGE support: WHEN MATCHED ... DELETE and conditional updates can also be written. For a single-row source, the dual table is used.
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;PostgreSQL's classic upsert is INSERT ... ON CONFLICT (unique column) DO UPDATE / DO NOTHING; the new values of the conflicting row are accessed through the EXCLUDED alias. Since PostgreSQL 15 the standard MERGE statement is also supported. ON CONFLICT is atomic on a single table and widely used.
MySQL
INSERT INTO customer (id, name, balance)
VALUES (1, 'Ali', 500)
ON DUPLICATE KEY UPDATE
name = VALUES(name), balance = VALUES(balance);MySQL/MariaDB use INSERT ... ON DUPLICATE KEY UPDATE for upserts; if a unique or primary key conflicts, the row is updated. New values are accessed with VALUES(my_column) (or the 'new.my_column' row alias in 8.0.19+). INSERT IGNORE silently skips the row on conflict. MySQL has no 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 supports the MERGE statement since 2008; it offers extra branches such as WHEN NOT MATCHED BY SOURCE for deleting surplus rows in the target. A MERGE statement must be terminated with a semicolon. Note: because of some edge-case bugs, writing separate INSERT/UPDATE statements may be preferred for simple upserts.
MongoDB
// Find-and-update or insert with upsert:true
db.customer.updateOne(
{ id: 1 },
{ $set: { name: "Ali", balance: 500 } },
{ upsert: true }
)In MongoDB upsert is a native option: if { upsert: true } is added to updateOne/updateMany/findOneAndUpdate, a matching document is updated, otherwise a new document is created. For bulk synchronization, the aggregation $merge stage (write/update into a target collection) is closer to SQL MERGE.
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 500In Redis write commands are inherently upserts: SET/HSET update the key or field if it exists, otherwise create it. Use the SET ... NX option to write only if absent, and XX only if present. The 'update if exists, else insert' distinction is already the default behavior of most commands.
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 an index (PUT) call with the same _id fully replaces the document if it exists, otherwise creates it (upsert-like). For partial updates with insert-if-absent, use 'doc_as_upsert': true or an 'upsert' block in the _update API. Scripted upserts are also possible.