A partir de la versión 2008 R2 de SQL Server tenemos disponible la sentencia Merge (). Esta sentencia permite actualizar una tabla objetivo basándose en el resultado de una unión con una tabla fuente. Es decir, puedo mantener actualizada una tabla en base a la información exigente en otra tabla, siempre y cuando las dos tengan un dato en común, como un código. Esta tarea facilita el mantenimiento de tablas de tipo maestro cuando la información se obtiene de diferentes fuentes o de fuentes externas. El efecto que se quiere lograr es que en una sola sentencia se puedan realizar varias aciones. Típicamente esto implica:
- Actualizar datos: Si se encuentra el código de unión tanto en la tabla de origen como en la de destino, se actualizan mediante un UPDATE los datos de la tabla de destino.
- Insertar datos: Si existe un código de unión en la tabla de origen pero no existe en la de destino, se inserta mediante un INSERT los datos en la tabla de destino.
- Eliminar datos: Si no existe un código de unión en la tabla de origen pero fi existe en la de destino, se elimina mediante un DELETE los datos de la tabla de destino.
Si desea obtener el script con los ejemplos, hacer clic en la sigiuente imagen:
Analicemos un caso: Supongamos que queremos actualizar nuestra tabla Empleado en base a una tabla que contiene la información actualizada (EmpleadoUpdate). revisemos los datos disponibles:
SELECT * FROM dbo.Empleado
SELECT * FROM dbo.EmpleadoUpdate
La primera parte de la sentencia debe definir la tabla de origen, la de destino y la condición de unión:
MERGE INTO dbo.Empleado AS e
USING dbo.EmpleadoUpdate AS eu
ON e.CodEmpleado = eu.CodEmpleado
…
Luego definimos las acciones a tomar según la condición de unión:
WHEN MATCHED.-Se utiliza cuando según la condición de unión, el dato se ubica tanto en la tabla de origen como en la de destino. La sentencia sería de la siguiente manera:
MERGE INTO dbo.Empleado AS e
USING dbo.EmpleadoUpdate AS eu
ON e.CodEmpleado = eu.CodEmpleado
WHEN MATCHED THEN
UPDATE SET e.NombreCompleto = eu.NombreCompleto, e.Estado = eu.Estado;
- En este caso, estamos tomando como ejemplo la acción típica de actualizar, pero además de la acción UPDATE se pueden ejecutar acciones de INSERT y DELETE
- Se puede incluir hasta dos condiciones WHHEN MATCHED. Ejemplo: WHEN MATCHED AND s.Quantity > 0 (NOTA: en este caso una debe ejecutar un UPDATE y la otra un DELETE)
- Luego de ejecutar la sentencia MERGE, observemos que se actualizó el estado del empleado 1 y el nombre del empleado 4:
SELECT * FROM dbo.EmpleadoUpdate
WHEN NOT MATCHED BY TARGET.-Se utiliza cuando según la condición de unión, el dato se ubica en la tabla de origen pero no se encuentra en la de destino. La sentencia sería de la siguiente manera:
MERGE INTO dbo.Empleado AS e
USING dbo.EmpleadoUpdate AS eu
ON e.CodEmpleado = eu.CodEmpleado
WHEN MATCHED THEN
UPDATE SET e.NombreCompleto = eu.NombreCompleto, e.Estado = eu.Estado
WHEN NOT MATCHED THEN
INSERT (CodEmpleado, NombreCompleto, Estado)
VALUES (eu.CodEmpleado, eu.NombreCompleto, eu.Estado);
- El uso de WHEN NOT MATCHED BY TARGET es opcional.
- En este caso, cuando la información no se encuentra en el destino, se están insertando los datos.
- Las palabras BY TARGET son opcionales
- Luego de ejecutar la sentencia MERGE, observemos que se actualizó el estado del empleado 1, el nombre del empleado 4 y se insertó el empleado 5:
SELECT * FROM dbo.EmpleadoUpdate
WHEN NOT MATCHED BY SOURCE.-Se utiliza cuando según la condición de unión, el dato no se ubica en la tabla de origen pero fi se encuentra en la de destino. La sentencia sería de la siguiente manera:
MERGE INTO dbo.Empleado AS e
USING dbo.EmpleadoUpdate AS eu
ON e.CodEmpleado = eu.CodEmpleado
WHEN MATCHED THEN
UPDATE SET e.NombreCompleto = eu.NombreCompleto, e.Estado = eu.Estado
WHEN MATCHED THEN
INSERT (CodEmpleado, NombreCompleto, Estado)
VALUES (eu.CodEmpleado, eu.NombreCompleto, eu.Estado)
WHEN NOT MATCHED BY SOURCE THEN
DELETE;
- El uso de WHEN NOT MATCHED BY SOURCE es opcional.
- En este caso, cuando la información no se encuentra en el origen, se están eliminando en el destino.
- Su utilización no es muy común, pero típicamente implica una acción DELETE.
OUTPUT.-Permite devolver las acciones realizadas en la fusión de datos. Se utiliza la variable $action para conocer la acción realizada para cada registro
MERGE INTO dbo.Empleado AS e
USING dbo.EmpleadoUpdate AS eu
ON e.CodEmpleado = eu.CodEmpleado
WHEN MATCHED THEN
UPDATE SET e.NombreCompleto = COALESCE(eu.NombreCompleto,e.NombreCompleto), e.Estado = COALESCE(eu.Estado,e.Estado)
WHEN NOT MATCHED THEN
INSERT (CodEmpleado, NombreCompleto, Estado)
VALUES (eu.CodEmpleado, eu.NombreCompleto, eu.Estado)
OUTPUT $action, inserted.CodEmpleado, deleted.CodEmpleado;
- El uso de OUTPUT es opcional
- Para obtener información de los datos trabajads se utilizan las tablas especiales INSERTED y DELETED (
)
- Luego de ejecutar la sentencia MERGE, la opción OUTPUT muestra en detalle las acciones realizadas:
Este tipo de operaciones también se pueden lograr utilizando de manera independiente sentencias UPDATE, INSERT y DELETE. Pero hay que tener en cuenta lo siguiente:
- La condición de unión de la sentencia MERGE debe ser desmentirían, es decir una fila en la tabla de origen debe coincidir solo con una fila en la tabla de destino. Si queremos actualizar muchas filas en la tabla de destino en base a una sola en la tabla de origen, debemos usar UPDATE.
- MERGE se desempeña mejor por que hace una sola pasada a todos los datos, mientras que hacer de manera separada UPDATE, INSERT y DELETE implica repasar todos los datos por cada sentencia.
Excelente articulo
Hola. como puede hacer que cada insert merge se ejecute un trigger, según las pruebas que hice el trigger solo se ejecuta una vez po n filas que inserte .
Gracias.
Manuel, efectivamente el trigger se ejecuta una vez por todo el conjunto de datos que se está insertando. Si requieres ejecutar algun código línea por línea, tienes que implementar un control de tipo WHILE con cursores o tablas temporalescomo parte del trigger.
Saludos
amigos se puede hacer un insert con select ya que algunos campos se le asigna valores fijos
Luis: no entiendo bien tu consulta. Puedes ampliar?