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.