web-dev-qa-db-fra.com

Lorsque vous effectuez un MERGE dans Oracle SQL, comment puis-je mettre à jour des lignes qui ne correspondent pas dans la SOURCE?

J'ai une base de données main et une base de données report, et je dois synchroniser une table de main dans report.

Cependant, lorsqu'un élément est supprimé dans la base de données main, je souhaite uniquement définir un indicateur IsDeleted dans la base de données report.

Quelle est la manière élégante de procéder?

J'utilise actuellement une instruction MERGE, comme ceci:

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...)
;

Le WHEN NOT MATCHED l'instruction me donne toutes les NOUVELLES valeurs de main, mais je veux aussi mettre à jour toutes les VIEILLES valeurs de report.

J'utilise Oracle PL/SQL.

13
Scott Rippey

Vous pouvez le faire avec une instruction UPDATE distincte

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

Je ne connais aucun moyen d'intégrer cela dans votre déclaration MERGE.

14
steve godfrey
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
5
Jon Heller

La réponse suivante est fusionner les données dans le même tablea

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');

Cette commande vérifie si USER_ID et USER_NAME sont mis en correspondance, sinon ils seront insérés.

4
Zafrullah Syed
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
Mark