Saltar al contenido

Sentencia MERGE INTO (UPSERT)

Antes de esta sentencia «MERGE INTO», que vino implementada en Oracle 9,  cuando se quería insertar/actualizar datos en una tabla que no estaba vacía, teníamos que ir procesando los registros y comprobar si estaba en la tabla antes de realizar un UPDATE o un INSERT, con algún tipo de lenguaje procesual.

Este tipo de sentencia permite actualizar registros (UPDATE) cuando la condición se cumple o insertar registros (INSERT) cuando la condición no se cumple.  Eso si, no es recomendable en cargas masivas de datos!

Esta sentencia tiene esta sintaxis:

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];

MERGE INTO RESTO res USING prueba_tmp pru

ON (res.ID = pru.ID)

WHEN MATCHED THEN

UPDATE SET

 res.DNI = pru.DNI,

 res.departamento = pru.departamento

WHEN NOT MATCHED THEN

INSERT (ID, DNI, DEPARTAMENTO)

VALUES (pru.ID, pru.DNI, pru.DEPARTAMENTO)

He intentado meter más condiciones en la clausula ON, pero no he podido y tampoco he visto información al respecto.

Esta sentencia tiene otras posibilidades:

–       Sólo  insert (NOT MATCHED):

MERGE INTO RESTO res USING prueba_tmp pru

ON (res.ID = pru.ID)

WHEN NOT MATCHED THEN

INSERT (ID, DNI, DEPARTAMENTO)

VALUES (pru.ID, pru.DNI, pru.DEPARTAMENTO)

–       Sólo update (MATCHED):

MERGE INTO RESTO res USING prueba_tmp pru

ON (res.ID = pru.ID)

WHEN MATCHED THEN

UPDATE SET

 res.DNI = pru.DNI,

 res.departamento = pru.departamento

–       Con condiciones en el INSERT o el UPDATE ( Las condiciones tienen que basarse en la tabla de la que se recoge los datos)

MERGE INTO RESTO RES USING PRUEBA_TMP PRU

ON (RES.ID = PRU.ID)

WHEN MATCHED THEN

UPDATE SET

 RES.DNI = PRU.DNI,

 RES.DEPARTAMENTO = PRU.DEPARTAMENTO

WHERE PRU.DEPARTAMENTO != ‘CONTABILIDAD’

WHEN NOT MATCHED THEN

INSERT (ID, DNI, DEPARTAMENTO)

VALUES (PRU.ID, PRU.DNI, PRU.DEPARTAMENTO)

WHERE PRU.DEPARTAMENTO != ‘Contabilidad’

–       Con Delete (Siempre con el UPDATE) Haremos un update y luego borraremos los que pertenezcan a un departamento en la tabla en la que hemos hecho el update:

MERGE INTO RESTO RES USING PRUEBA_TMP PRU

ON (RES.ID = PRU.ID)

WHEN MATCHED THEN

UPDATE SET

 RES.DNI = PRU.DNI,

 RES.DEPARTAMENTO = PRU.DEPARTAMENTO

DELETE WHERE PRU.DEPARTAMENTO =  ‘Contabilidad’

 –       Si queremos utilizarla con parámetros y la tabla DUAL:

 MERGE INTO RESTO res

USING dual d

ON (res.ID = PARAMETRO1)

WHEN MATCHED THEN UPDATE SET res.DNI = PARAMETRO2

WHEN NOT MATCHED THEN INSERT (res.ID, res.DNI) VALUES (PARAMETRO1, PARAMETRO2);

Si el MERGE nos devuelve el siguiente error:

“ORA-30926: unable to get a stable set of rows in the source tables.

Cause: A stable set of rows could not be got because of large dml activity or a non-deterministic where clause.

Action: Remove any non-deterministic where clauses and reissue the dml.”

La verdadera causa del error no está en el “non-deterministic where clause“: quiere decir que hay dos filas de la tabla origen que actualizarían una de la tabla destino.