MERGE / UPSERT (actualizar si existe; si no, insertar)
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) compara un origen con un destino, actualiza las filas coincidentes e inserta las no coincidentes; ideal para la sincronización masiva de datos. Oracle tiene un soporte sólido de MERGE: también se pueden escribir WHEN MATCHED ... DELETE y actualizaciones condicionales. Para un origen de una sola fila se usa la tabla dual.
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;El upsert clásico de PostgreSQL es INSERT ... ON CONFLICT (columna única) DO UPDATE / DO NOTHING; a los nuevos valores de la fila en conflicto se accede mediante el alias EXCLUDED. Desde PostgreSQL 15 también se admite la sentencia MERGE estándar. ON CONFLICT es atómico sobre una sola tabla y muy usado.
MySQL
INSERT INTO customer (id, name, balance)
VALUES (1, 'Ali', 500)
ON DUPLICATE KEY UPDATE
name = VALUES(name), balance = VALUES(balance);MySQL/MariaDB usan INSERT ... ON DUPLICATE KEY UPDATE para los upserts; si hay conflicto con una clave única o primaria, la fila se actualiza. A los nuevos valores se accede con VALUES(my_column) (o con el alias de fila 'new.my_column' en 8.0.19+). INSERT IGNORE omite silenciosamente la fila en caso de conflicto. MySQL no tiene MERGE estándar.
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 admite la sentencia MERGE desde 2008; ofrece ramas adicionales como WHEN NOT MATCHED BY SOURCE para eliminar las filas sobrantes en el destino. Una sentencia MERGE debe terminar con punto y coma. Nota: debido a algunos bugs en casos límite, para upserts sencillos puede preferirse escribir sentencias INSERT/UPDATE separadas.
MongoDB
// Find-and-update or insert with upsert:true
db.customer.updateOne(
{ id: 1 },
{ $set: { name: "Ali", balance: 500 } },
{ upsert: true }
)En MongoDB el upsert es una opción nativa: si se añade { upsert: true } a updateOne/updateMany/findOneAndUpdate, se actualiza el documento coincidente o, si no existe, se crea uno nuevo. Para la sincronización masiva, la etapa de agregación $merge (escribir/actualizar en una colección de destino) se acerca más a MERGE de SQL.
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 500En Redis los comandos de escritura son upserts por naturaleza: SET/HSET actualizan la clave o el campo si existe y, si no, lo crean. Use la opción SET ... NX para escribir solo si no existe, y XX solo si existe. La distinción 'actualizar si existe; si no, insertar' ya es el comportamiento por defecto de la mayoría de los comandos.
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 }En Elasticsearch, una llamada index (PUT) con el mismo _id reemplaza por completo el documento si existe y, si no, lo crea (similar a un upsert). Para actualizaciones parciales con inserción si no existe, use 'doc_as_upsert': true o un bloque 'upsert' en la API _update. También son posibles los upserts con script.