miércoles, 27 de febrero de 2008

Insertar o actualizar un único registro con MERGE

La versión 9i de Oracle Database traía entre sus SQL features, la incorporación de una novedosa sentencia: MERGE (ahora parte del estándar ANSI SQL). Hasta ese momento, cuando se quería insertar/actualizar datos en una tabla no vacía, había que revisar si el registro ya existía para aplicar INSERT o UPDATE, manejándolo proceduralmente con algún lenguaje, por ejemplo PL/SQL. Con MERGE, podemos tener esta lógica en una única sentencia SQL, simplificando el código y haciendo la tarea más performante.

La sintáxis de MERGE está pensada para que la fuente de datos que se va a insertar sea una tabla o una consulta, de esta manera:

MERGE INTO [tabla_destino]
USING ([tabla o vista o consulta])
ON ([condición de existencia de registro])
WHEN MATCHED THEN [sentencia de actualización]

WHEN NOT MATCHED THEN [sentencia de inserción];

Hay veces en que los datos a incorporar no provienen de ninguna tabla, sino que se trata de un único registro enviado por una aplicación (por ejemplo a través de parámetros). Una forma de poder aprovechar la sentencia MERGE en estos casos, es construir una consulta sobre la tabla DUAL que convenientemente contiene una única fila.

Partiendo de una tabla tabla_destino, donde queremos hacer la actualización de datos:
CREATE TABLE tabla_destino (a int, b varchar2(10));

Si:
  • Nuestro registro a insertar es {param_a, param_b}
  • La condición de que el registro exista es la columna a
  • Lo que queremos actualizar en caso que el registro exista es la columna b
...entonces usamos MERGE así:

1 MERGE INTO tabla_destino td
2 USING (SELECT param_a a FROM dual) d
3 ON (td.a = d.a)
4 WHEN MATCHED THEN UPDATE SET td.b = param_b
5 WHEN NOT MATCHED THEN INSERT (td.a, td.b) VALUES (param_a, param_b);

En la línea 2 (USING) seleccionamos el registro que participa en la condición que el registro exista.
En la línea 3 especificamos cual es la condición que se considera que el registro ya existe
Las líneas 4 y 5 actualizan o insertan el registro.

Una forma simplificada y equivalente es la siguiente:

MERGE INTO tabla_destino td
USING dual d
ON (td.a = param_a)
WHEN MATCHED THEN UPDATE SET td.b = param_b
WHEN NOT MATCHED THEN INSERT (td.a, td.b) VALUES (param_a, param_b);

Se recomienda el uso de MERGE ya que es una única sentencia SQL y naturalmente está optimizada por el motor. Hay excepciones como es el caso de cargas masivas de datos con millones de registros donde la performance de MERGE se degrada. Allí existen otras alternativas más eficientes.

Ver también:
Oracle 9i SQL Reference para MERGE
Oracle 10g SQL Reference para MERGE
Update condicional

5 comentarios:

Anónimo dijo...

muy útil, gracias

Unknown dijo...

gracias ... muy útil

Anónimo dijo...

Muchísimas gracias, cuando ves un post que te deja las cosas tan nítidas es de agradecer.

Anónimo dijo...

Yo no entendi :D

Geymer Morales Cruz dijo...

Excelente muchas gracias muy útil