Sunteți pe pagina 1din 5

Sentencia MERGE

SQL y PL/SQL - La nueva sentencia MERGE

La sentencia MERGE, a la que muchos denominan UPSERTdebido a su funcionalidad, está


disponible desde la aparición de la versión 9i de la base de datos Oracle. Se trata de una de las
funcionalidades del kerneltecnología ETLExtract, Transform and Load - Extraer, Transformar y
Cargar) con las bases de datos Oracle. Este tipo de tecnología puede utilizarse y está
especialmente enfocada para ser usada en aplicaciones de data warehousing (almacen de datos).
Básicamente, lo que permite la sentencia SQL MERGE es, dependiendo de una condición
lógica, actualizar registros (UPDATE) cuando la condición se cumple, o insertar registros
(INSERT) cuando dicha condición no se cumple, de ahí surge la denominación de UPSERT.
de Oracle más utiles a la hora de permitir el uso de la (

Anteriormente a la versión 9i de Oracle, la alternativa en SQL era ejecutar dos sentencias DML,
unUPDATE y un INSERT, cada una utilizando condiciones lógicas opuestas. En cuanto a las
alternativas en PL/SQL eran: bien intentar insertar un registro y si la sentencia INSERT fallaba
debido a una excepcion PLSQL del tipo DUP_VAL_ON_INDEX, entonces realizar
unUPDATEUPDATE devolvía SQL%NOTFOUND, entonces ejecutar la correspondiente
sentenciaINSERT.

Las ventajas de la sentencia SQL MERGE son claras:

- Permite con una misma sentencia realizar un UPDATE si el registro existe, o un INSERT si se
trata de un nuevo registro.

- La sentencia puede paralelizarse de forma transparente.

- Se evita la necesidad de realizar actualizaciones múltiples.

- Es especialmente útil para realizar operaciones en masa y, como ya he mencionado, en


aplicaciones de data warehousing.

- El rendimiento de la base de datos mejora ya que, al necesitarse menos sentencias SQL para
realizar las mismas operaciones, también se necesitan menos accesos a las tablas fuente.

Ejemplo de sentencia MERGE

En el presente ejemplo voy a partir del hecho de que tenemos dos tablas en un data warehouse,
una de ellas con muchos registros denominada clientes y otra más pequeña denominada
datos_cli cuyos registros deben insertarse en la tabla clientes. En pocas palabras, estoy
suponiendo que la tabla datos_cli contiene los cambios a realizar sobre la tabla clientes. La
sentencia SQL MERGE que debemos utilizar para actualizar la tabla cliente podría ser la siguiente:

del registro en cuestión; bien intentar actualizar un registro y si la sentencia

MERGE INTO clientes cli USING datos_cli dac


ON (cli.cliente_id = dac.cliente_id)
WHEN MATCHED THEN
UPDATE SET
cli.nombre = dac.nombre,
cli.direccion = dac.direccion
WHEN NOT MATCHED THEN
INSERT (cliente_id, nombre, direccion)
VALUES (dac.cliente_id, dac.nombre, dac.direccion);

Así pues, la sentencia MERGE del ejemplo realizará las siguientes operaciones:

- Si existe un registro en datos_cli con el mismo ID de otro registro en la tabla clientes, entoces


actualizará el valor de los campos nombre y dirección de la tabla clientes con los valores
correspondientes de la tabla datos_cli.

- Si no existe un registro en clientes con el ID del registro de datos_cli que está siendo procesado,


entonces se insertará dicho registro en la tabla clientes.

En resumen, la sintaxis de la sentencia MERGE debe incorporar:

Una cláusula INTO, que especifica la tabla destino donde los registros serán actualizados o
insertados.

Una cláusula USING, especificando el origen de los datos que van a ser insertados o que van a
servir para actualizar la tabla destino. El origen de los datos puede tratarse de una tabla, una vista,
o del resultado de la ejecución de una consulta SELECT.

Una cláusula ON, que especifica la condición bajo la cual se realizará, bien la


operaciónUPDATE (si la condición se cumple), bien la operación INSERT (si la condición no se
cumple).

Las cláusulas WHEN MATCHED | NOT MATCHED, que son las que indican a la base de datos
Oracle que acción realizar si se cumple o no se cumple la condición del ON. Estas dos cláusulas se
pueden poner en cualquier orden.
GE
Con Oracle 9i se introduce la expresión MERGE.  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, por ejemplo PL/SQL. Con MERGE, podemos tener esta lógica en una única
sentencia SQL, simplificando el código y obteniendo un mejor rendimiento.

MERGE <hint> INTO <table_name>


USING <table_view_or_query>
ON (<condition>)
WHEN MATCHED THEN <update_clause>
DELETE <where_clause>
WHEN NOT MATCHED THEN <insert_clause>

[LOG ERRORS <log_errors_clause> <reject limit <integer | unlimited>];

En Oracle 10g se introducen mejoras, de modo que puede hacerse sólo el Update (sin poner claúsula "WHEN
NOT MATCHED") y viceversa (indicar sólo el Insert, obviando la claúsula "WHEN MATCHED"), además de
incluir la posibilidad de poner una sentencia DELETE justo después del UPDATE para borrar las filas del
"MATCH" que cumplan una determinada condición.

Ejemplos:
-- Con Update cuando la fila existe, e Insert cuando no
MERGE INTO test1 a
USING all_objects b
ON (a.object_id = b.object_id)
WHEN MATCHED THEN
UPDATE SET a.status = b.status
WHERE b.status != 'VALID'
WHEN NOT MATCHED THEN
INSERT (object_id, status)
VALUES (b.object_id, b.status)
WHERE b.status != 'VALID';

-- Sólo con Insert


MERGE INTO test1 a
USING all_objects b
ON (a.object_id = b.object_id)
WHEN NOT MATCHED THEN
INSERT (object_id, status)
VALUES (b.object_id, b.status)
WHERE b.status != 'VALID';

-- Sólo con Update


MERGE INTO test1 a
USING all_objects b
ON (a.object_id = b.object_id)
WHEN MATCHED THEN
UPDATE SET a.status = b.status
WHERE b.status != 'VALID';

-- Con Delete después de hacer el Update


MERGE INTO test1 a
USING all_objects b
ON (a.object_id = b.object_id)
WHEN MATCHED THEN
UPDATE SET a.status = b.status
WHERE b.status != 'VALID'
DELETE WHERE (b.status = 'VALID');

Guia_del_Alumno_Volumen1 pag 114 PDF

http://psoug.org/reference/merge.html

CREATE TABLE employee (


employee_id NUMBER(5),
first_name VARCHAR2(20),
last_name VARCHAR2(20),
dept_no NUMBER(2),
salary NUMBER(10));

INSERT INTO employee VALUES (1, 'Dan', 'Morgan', 10, 100000);


INSERT INTO employee VALUES (2, 'Helen', 'Lofstrom', 20, 100000);
INSERT INTO employee VALUES (3, 'Akiko', 'Toyota', 20, 50000);
INSERT INTO employee VALUES (4, 'Jackie', 'Stough', 20, 40000);
INSERT INTO employee VALUES (5, 'Richard', 'Foote', 20, 70000);
INSERT INTO employee VALUES (6, 'Joe', 'Johnson', 20, 30000);
INSERT INTO employee VALUES (7, 'Clark', 'Urling', 20, 90000);

select * from employee;


CREATE TABLE bonuses (
employee_id NUMBER, bonus NUMBER DEFAULT 100);

INSERT INTO bonuses (employee_id) VALUES (1);


INSERT INTO bonuses (employee_id) VALUES (2);
INSERT INTO bonuses (employee_id) VALUES (4);
INSERT INTO bonuses (employee_id) VALUES (6);
INSERT INTO bonuses (employee_id) VALUES (7);

MERGE INTO bonuses b


USING (
SELECT employee_id, salary, dept_no
FROM employee
WHERE dept_no =20) e
ON (b.employee_id = e.employee_id)
WHEN MATCHED THEN
UPDATE SET b.bonus = e.salary * 0.1
DELETE WHERE (e.salary < 40000)
WHEN NOT MATCHED THEN
INSERT (b.employee_id, b.bonus)
VALUES (e.employee_id, e.salary * 0.05)
WHERE (e.salary > 40000);

select * from bonuses;


WHEN MATCHED THEN
2
4
6
7
WHEN NOT MATCHED THEN
3
5

S-ar putea să vă placă și