2012-05-10 23 views
12

Tengo una base de datos main y una base de datos report, y necesito sincronizar una tabla desde main en report.Al hacer un MERGE en Oracle SQL, ¿cómo puedo actualizar las filas que no coinciden en el SOURCE?

Sin embargo, cuando un elemento se elimina en la base de datos main, solo quiero establecer un indicador IsDeleted en la base de datos report.

¿Qué es una forma elegante de hacer esto?

Actualmente estoy usando una instrucción MERGE, así:

MERGE INTO report.TEST target 
USING (SELECT * FROM main.TEST) source 
    ON (target.ID = source.ID) 
WHEN MATCHED THEN 
    UPDATE SET (target... = source...) 
WHEN NOT MATCHED THEN 
    INSERT (...) VALUES (source...) 
; 

La declaración WHEN NOT MATCHED me da todos los nuevos valores de main, pero también quiero poner al día todos los viejos valores de report.

Estoy usando Oracle PL/SQL.

+0

¿Con qué valores desea actualizar 'main.test'? ¿De dónde los sacarías? –

+0

Si la fila se borra de 'main.test', entonces la fila' report.test' correspondiente no tendrá igual. Quiero establecer el indicador 'report.test.IsDeleted' para todas las filas no coincidentes. –

+0

No creo que sea posible ya que el resultado de JOIN subyacente ('using (...)') no contendrá esa fila. Entonces, ¿de dónde deberían venir esos datos? –

Respuesta

11

Usted puede hacerlo con una instrucción UPDATE separada

UPDATE report.TEST target 
SET is Deleted = 'Y' 
WHERE NOT EXISTS (SELECT 1 
        FROM main.TEST source 
        WHERE source.ID = target.ID); 

No sé de cualquier manera de integrar este principio en su sentencia MERGE.

+0

Parece extraño que no pueda hacer esto con MERGE. Consideraré esta respuesta. –

+0

¿Sería más "elegante"/eficiente si hiciera una 'UNIÓN EXTERIOR', y actualizara donde 'main.test es nulo'? –

+1

Hay una pregunta relacionada aquí http://stackoverflow.com/questions/4863960/could-somebody-explain-what-the-merge-statement-really-does-in-oracle, creo que hará una combinación externa, no es una combinación externa completa, así que no creo que lo que hayas sugerido funcione. –

4
MERGE INTO target 
USING 
(
    --Source data 
    SELECT id, some_value, 0 deleteMe FROM source 
    --And anything that has been deleted from the source 
    UNION ALL 
    SELECT id, null some_value, 1 deleteMe 
    FROM 
    (
     SELECT id FROM target 
     MINUS 
     SELECT id FROM source 
    ) 
) source 
    ON (target.ID = source.ID) 
WHEN MATCHED THEN 
    --Requires a lot of ugly CASE statements, to prevent updating deleted data 
    UPDATE SET target.some_value = 
     CASE WHEN deleteMe=1 THEN target.some_value ELSE source.some_value end 
    ,isDeleted = deleteMe 
WHEN NOT MATCHED THEN 
    INSERT (id, some_value, isDeleted) VALUES (source.id, source.some_value, 0) 

--Test data 
create table target as 
select 1 ID, 'old value 1' some_value, 0 isDeleted from dual union all 
select 2 ID, 'old value 2' some_value, 0 isDeleted from dual; 

create table source as 
select 1 ID, 'new value 1' some_value, 0 isDeleted from dual union all 
select 3 ID, 'new value 3' some_value, 0 isDeleted from dual; 


--Results: 
select * from target; 

ID SOME_VALUE ISDELETED 
1 new value 1 0 
2 old value 2 1 
3 new value 3 0 
+0

¡Gracias por ser creativo! No voy a hacer esto, pero hace el trabajo. –

-1
merge into x as target using y as Source on target.ID = Source.ID 
when not matched by target then insert 
when matched then update 
when not matched by source and target.ID is not null then 
update whatevercolumn = 'isdeleted' ; 
+0

¿dónde encontraste esta sintaxis? ('by target') –

+0

Esto es exactamente lo que estoy buscando ... sin embargo, como dijo @FlorinGhita, ¿dónde encontraste esta sintaxis? ¿Es esta sintaxis MS SQL? –

+6

-1, ya que se trata de la sintaxis [combinación de SQL Server] (http://msdn.microsoft.com/en-us/library/bb510625.aspx) [fusión de Oracle] (http://docs.oracle.com/cd /E11882_01/server.112/e26088/statements_9016.htm#SQLRF01606) – user272735

2

La siguiente respuesta es datos de combinación en la misma mesa

MERGE INTO YOUR_TABLE d 
USING (SELECT 1 FROM DUAL) m 
    ON (d.USER_ID = '123' AND d.USER_NAME= 'itszaif') 
WHEN NOT MATCHED THEN 
     INSERT (d.USERS_ID, d.USER_NAME) 
     VALUES ('123','itszaif'); 

Este comando comprueba si USER_ID y USER_NAME se emparejan, si no coincide, entonces se inserte.

Cuestiones relacionadas