martes, 27 de noviembre de 2012

Sentencia Merge - Oracle SQL y Plsql

La sentencia Merge nos sirve para combinar dos operaciones: Insertar y Actualizar. La función Merge nos permite hacer un update en caso de que la condición dada se cumpla o insertar en caso de que no se cumpla, es realmente muy útil.

Se puede usar a partir de Oracle 9i.

La sintaxis:



MERGE INTO <table_name>
USING <table_view_or_query>
ON (<condition>)
WHEN MATCHED THEN <update_clause>
WHEN NOT MATCHED THEN <insert_clause>
[LOG ERRORS <log_errors_clause> <reject limit <integer | unlimited>];



TABLE_NAME
Aqui debe especificar el nombre de la tabla o vista en la que va a insertar o actualizar. Si va a hacer un merge sobre una vista, ésta debe ser actualizable.

TABLE_VIEW_OR_SUBQUERY
En está se indica el origen de los datos que va a actualizar, puede ser una tabla, una vista o un subquery.

CONDITION
Especificas la condición para que el merge decida si debe actualizar o insertar. Esta condición es evaluada fila por fila, si la condición es verdadera, se ejecutará la clausula Update; si la condición es falsa, la base de datos insertará el registro desde el origen.

UPDATE_CLASE
Especifica los nuevos valores de la tabla a actualizar, en caso de que la condición sea verdadera. No puedes actualizar una columna que éste incluida en la Condición.

INSERT_CLAUSE
Especifíca los valores a insertar en caso de que la condición no sea verdadera. 

EJEMPLO

En el ejemplo tenemos una tabla de descuentos a clientes (desc_client), está llena con los clientes de la empresa con derecho a descuento hasta el momento. La tabla está asi

Id     Porc_desc
111      10
112      10
115      15
212      20

Vamos a hacer una sentencia para que a los clientes que han comprado más de 200 pesos en el año se les incluya en la tabla de descuentos con un 10% y a los que ya están se les suba le 1% (Es solo un ejemplo)

La sentencia sería:


MERGE INTO desc_client d
USING (select id, sum(valor) from facturas where anio=2012
       group by id having sum(valor)>200) f
ON (d.id=f.id)

WHEN MATCHED THEN update set d.porc_desc = d.porc_desc + 1
WHEN NOT MATCHED THEN insert (d.id, d.porc_desc)

values (f.id, 10);

El resultado, suponiendo que los clientes 111,115,205,206 superaron los 200 pesos en compras, sería:

Id     Porc_desc
111      11
112      10
115      16
212      20
205      10
206      10