MERGE table, do nothing when matched

24,175

Solution 1

For your case, no need to use the part:

WHEN MATCHED THEN UPDATE ...

( using WHEN MATCHED THEN UPDATE SET a.id = a.id is accepted(Oracle doesn't hurl) but has no impact, so, such a usage is redundant, because you don't want to change anything for the matching case. )

If you wanted to change, then add

WHEN MATCHED THEN UPDATE SET a.id = b.id

before WHEN NOT MATCHED THEN INSERT...

( e.g.Oracle supports WHEN MATCHED THEN UPDATE syntax. Refer the Demo below )

Go on with the following for the current case :

SQL> CREATE TABLE domains( 
                           id          INT, 
                           name        VARCHAR2(50), 
                           code        VARCHAR2(50), 
                           description VARCHAR2(50)
                         );

SQL> INSERT INTO domains VALUES(1,'Domain A','D.A.','This is Domain A');

SQL> MERGE INTO domains A USING 
     (SELECT 2 id, 'Domain A' name, 'D.A.' code, 'This is Domain A' description 
        FROM domains) b
          ON ( a.name = b.name )
        WHEN NOT MATCHED THEN INSERT( a.id, a.name, a.code, a.description ) 
                              VALUES( b.id, b.name, b.code, b.description );

SQL> SELECT * FROM domains;

ID  NAME        CODE    DESCRIPTION
--  --------   -----  ----------------
1   Domain A    D.A.  This is Domain A

SQL> DELETE domains;

SQL> INSERT INTO domains VALUES(1,'Domain A','D.A.','This is Domain A');
-- we're deleting and inserting the same row again

SQL> MERGE INTO domains A USING       
 (SELECT 2 id, 'Domain B' name, 'D.B.' code, 'This is Domain B' description 
    FROM domains) b
      ON ( a.name = b.name )
    WHEN NOT MATCHED THEN INSERT( a.id, a.name, a.code, a.description ) 
                          VALUES( b.id, b.name, b.code, b.description );


SQL> SELECT * FROM domains;

ID  NAME        CODE    DESCRIPTION
--  --------   -----  ----------------
1   Domain A    D.A.  This is Domain A
2   Domain B    D.B.  This is Domain B

Demo

Solution 2

Oracle SQL syntax supports not having any when matched then update clause.

drop table ft purge;
create table ft (c1 number, c2 varchar2(10));

drop table ld purge;
create table ld (c1 number, c2 varchar2(10));

insert into ft values (1,'a');
insert into ld values (1,'b');
insert into ld values (2,'c');
commit;

merge into ft 
using ld
on (ft.c1 = ld.c1) 
when not matched then
insert (c1,c2) values (ld.c1,ld.c2);

select * from ft;

C1  C2
--- ---
1   a
2   c

2 rows selected.
Share:
24,175
user2102665
Author by

user2102665

Updated on October 08, 2021

Comments

  • user2102665
    user2102665 over 2 years

    I have a table DOMAINS in 2 different schemas with columns ID, NAME,CODE,DESCRIPTION.

    For any NAME exist in new schema, it should use existing ID without any merge; for those new NAME records, it should insert with ID from old schema.

    MERGE INTO DOMAINS A
    USING (SELECT ID,NAME,CODE,DESCRIPTION FROM <Old Schema 6.1>.DOMAINS@DB_MIG_61_TO_74) B
    ON(A.NAME = B.NAME)
    WHEN MATCHED **<do nothing>**
    WHEN NOT MATCHED THEN INSERT(A.ID,A.NAME,A.CODE,A.DESCRIPTION) 
    VALUES(B.ID,B.NAME,B.CODE,B.DESCRIPTION);
    

    How can i intepret the portion of do nothing in above query?

  • Shannon Fallon
    Shannon Fallon over 4 years
    This works better than the chosen solution when you have a column that shows when the row was last updated that you don't want to change when there's a match.
  • Barbaros Özhan
    Barbaros Özhan over 4 years
    No, when matched then update is supported