¿No os ha pasado nunca, buscando la resolución a un problema tras una migración de datos, o preparando un Upgrade de versiones, tener la necesidad de comparar datos entre dos tablas?
Muchos recurren a una sentencia SELECT, utilizando en el WHERE un NOT EXISTS;
La sentencia anterior busca registros de la tabla1 que no existan en la tabla2, uniendo por el campo1. Parece que funciona. Y de hecho lo hace: lo que no estamos teniendo en cuenta es la poca performance que la consulta tiene, sobre todo con grandes volúmenes de datos, o si alguna de las tablas se encuentra alojada en otra instancia y tendríamos que utilizar un servidor vinculado, etc. Además, y no de menor importancia, solo nos informa de los registros que no existen, sin realizar ninguna acción, es decir, qué deseamos hacer con las diferencias detectadas.
Comparativa de tablas con MERGE
Veamos el mismo ejemplo (tabla1 y tabla2 con los 3 campos que se pueden unir por campo1), utilizando MERGE.
Analizando la instrucción, podemos desglosar su funcionamiento:
- Utiliza la tabla2 como destino (MERGE INTO)
- Utiliza la tabla1 como origen (USING)
- Une ambas tablas por campo1 (ON)
- WHEN matched (cuando exista el registro en el destino), lo actualiza
- WHEN not matched by target (cuando no exista el registro en el destino), lo agrega o inserta
- WHEN not matched by source (cuando exista el registro en el destino y no exista en el origen), lo elimina del origen
Como podemos apreciar, no solo evalúa las diferencias, sin que nos permite realizar una acción por cada clase de diferencia que se encuentre. NO es obligatorio utilizar todas las opciones:si por ejemplo, no queremos actualizar los registros existentes en ambas tablas, no utilizamos la sección WHEN matched.
La performance de la instrucción completa, aún con grandes volúmenes de datos, se comporta realmente muy bien. Hasta puede estar contenida dentro de una transacción, de un procedimiento almacenado, etc.
Pero MERGE va un poco más allá y nos permite “conocer” los cambios que se aplicaron agregando un LOG en la instrucción.
Luego podemos ejecutar un SELECT * FROM <modificaciones>, donde <modificaciones> puede ser una tabla física de la base de datos para almacenar log’s, una variable local (@) de tipo table o una tabla temporal (#). $action devuelve la acción llevada a cabo, (en nuestro ejemplo, Insert, Update o Delete). También podríamos utilizar, además de $action, las variables de sesión de SQL inserted o deleted para recuperar las filas insertadas y/ actualizadas o eliminadas.
Tal como vimos, cuando nos encontramos en una situación en la cual debemos comparar datos, no os olvidemos la gran utilidad que aporta MERGE.