MERGE: comparar una fuente con una tabla de destino
Una carga puede traer filas que debemos insertar cuando son nuevas y actualizar cuando ya existen. MERGE expresa esa comparación mediante una fuente —el conjunto entrante—, un destino —la tabla que recibirá los cambios— y varias acciones condicionadas.
La sintaxis concentra la intención, pero también reúne varias operaciones en una sola instrucción. La usamos cuando mejora realmente la claridad y después de probar concurrencia —ejecuciones simultáneas sobre los mismos datos—, restricciones, disparadores y volumen.
Forma general
MERGE INTO dbo.TablaDestino AS destino
USING origen
ON destino.Clave = origen.Clave
WHEN MATCHED THEN
UPDATE SET Columna = origen.Columna
WHEN NOT MATCHED BY TARGET THEN
INSERT (Clave, Columna)
VALUES (origen.Clave, origen.Columna)
OUTPUT
$action,
inserted.Clave;
El punto y coma final es obligatorio. La condición ON establece únicamente cómo se emparejan fuente y destino; los filtros de cada acción se escriben en su cláusula WHEN.
Sincronizar una carga pequeña
DECLARE @Categorias TABLE
(
IdCategoria SMALLINT NULL,
Nombre NVARCHAR(80) NOT NULL
);
INSERT INTO @Categorias (IdCategoria, Nombre)
VALUES
(1, N'Accesorios y conectividad'),
(NULL, N'Liquidación');
MERGE INTO dbo.Categoria AS destino
USING @Categorias AS origen
ON destino.IdCategoria = origen.IdCategoria
WHEN MATCHED
AND destino.Nombre <> origen.Nombre THEN
UPDATE SET
Nombre = origen.Nombre
WHEN NOT MATCHED BY TARGET THEN
INSERT (Nombre)
VALUES
(
origen.Nombre
)
OUTPUT
$action AS Accion,
inserted.IdCategoria,
deleted.Nombre AS NombreAnterior,
inserted.Nombre AS NombreNuevo;
$action indica si cada fila fue insertada, actualizada o eliminada. La salida no tiene un orden garantizado.
El valor NULL, que representa un dato ausente o desconocido, no se inserta en la columna IDENTITY; únicamente hace que esa fila no encuentre correspondencia y SQL Server genere una nueva clave. Una columna IDENTITY produce automáticamente un número para cada fila nueva. El contrato de la carga debe definir con precisión qué significa una clave ausente.
La fuente debe ser coherente
Si más de una fila de la fuente coincide con la misma fila de destino y la acción intenta actualizarla, SQL Server genera un error. Normalizamos o rechazamos duplicados antes de ejecutar la sincronización.
La clave de comparación es el valor o conjunto de valores que identifica la correspondencia. Debe protegerse según la regla del negocio, normalmente mediante una restricción o índice único, que impide repetir esa clave. Sin esa protección, la lógica puede parecer correcta y aun así producir duplicados bajo concurrencia.
No agregar filtros impropios al ON
-- Evitar usar el ON para ocultar filas del destino.
ON destino.IdProducto = origen.IdProducto
AND destino.Activo = 1
Esa condición puede hacer que una fila existente sea tratada como no coincidente y conducir a resultados inesperados. Conservamos en ON las columnas de correspondencia y colocamos condiciones adicionales en el WHEN apropiado.
Cuándo preferir instrucciones separadas
Si solo necesitamos actualizar desde otra tabla, o si la lógica se entiende mejor como pasos independientes, UPDATE, INSERT y DELETE separados pueden ser más claros y escalables. También simplifican aislar planes, errores y efectos de cada operación.
No incluimos WHEN NOT MATCHED BY SOURCE THEN DELETE por reflejo. Una fuente parcial no representa necesariamente todo el universo y podría eliminar filas válidas.
Qué conviene comprobar
Probamos con duplicados, ejecuciones concurrentes, restricciones, disparadores, errores intermedios y volúmenes representativos. Revisamos índices sobre las claves de unión y capturamos OUTPUT cuando necesitamos auditar las acciones.
MERGE no reemplaza el diseño de una carga idempotente —una operación que puede repetirse sin acumular cambios indebidos— ni el control transaccional, que confirma o revierte una unidad de trabajo. Es una construcción disponible, no una obligación para toda sincronización.