Oracle: how to UPSERT (update or insert into a table?)

后端 未结 12 1385
南旧
南旧 2020-11-22 07:18

The UPSERT operation either updates or inserts a row in a table, depending if the table already has a row that matches the data:

if table t has a row exists          


        
相关标签:
12条回答
  • 2020-11-22 08:08

    I'd like Grommit answer, except it require dupe values. I found solution where it may appear once: http://forums.devshed.com/showpost.php?p=1182653&postcount=2

    MERGE INTO KBS.NUFUS_MUHTARLIK B
    USING (
        SELECT '028-01' CILT, '25' SAYFA, '6' KUTUK, '46603404838' MERNIS_NO
        FROM DUAL
    ) E
    ON (B.MERNIS_NO = E.MERNIS_NO)
    WHEN MATCHED THEN
        UPDATE SET B.CILT = E.CILT, B.SAYFA = E.SAYFA, B.KUTUK = E.KUTUK
    WHEN NOT MATCHED THEN
        INSERT (  CILT,   SAYFA,   KUTUK,   MERNIS_NO)
        VALUES (E.CILT, E.SAYFA, E.KUTUK, E.MERNIS_NO); 
    
    0 讨论(0)
  • 2020-11-22 08:12

    A note regarding the two solutions that suggest:

    1) Insert, if exception then update,

    or

    2) Update, if sql%rowcount = 0 then insert

    The question of whether to insert or update first is also application dependent. Are you expecting more inserts or more updates? The one that is most likely to succeed should go first.

    If you pick the wrong one you will get a bunch of unnecessary index reads. Not a huge deal but still something to consider.

    0 讨论(0)
  • 2020-11-22 08:13

    Another alternative without the exception check:

    UPDATE tablename
        SET val1 = in_val1,
            val2 = in_val2
        WHERE val3 = in_val3;
    
    IF ( sql%rowcount = 0 )
        THEN
        INSERT INTO tablename
            VALUES (in_val1, in_val2, in_val3);
    END IF;
    
    0 讨论(0)
  • 2020-11-22 08:13
    1. insert if not exists
    2. update:
        
    INSERT INTO mytable (id1, t1) 
      SELECT 11, 'x1' FROM DUAL 
      WHERE NOT EXISTS (SELECT id1 FROM mytble WHERE id1 = 11); 
    
    UPDATE mytable SET t1 = 'x1' WHERE id1 = 11;
    
    0 讨论(0)
  • 2020-11-22 08:13

    Try this,

    insert into b_building_property (
      select
        'AREA_IN_COMMON_USE_DOUBLE','Area in Common Use','DOUBLE', null, 9000, 9
      from dual
    )
    minus
    (
      select * from b_building_property where id = 9
    )
    ;
    
    0 讨论(0)
  • 2020-11-22 08:16

    I've been using the first code sample for years. Notice notfound rather than count.

    UPDATE tablename SET val1 = in_val1, val2 = in_val2
        WHERE val3 = in_val3;
    IF ( sql%notfound ) THEN
        INSERT INTO tablename
            VALUES (in_val1, in_val2, in_val3);
    END IF;
    

    The code below is the possibly new and improved code

    MERGE INTO tablename USING dual ON ( val3 = in_val3 )
    WHEN MATCHED THEN UPDATE SET val1 = in_val1, val2 = in_val2
    WHEN NOT MATCHED THEN INSERT 
        VALUES (in_val1, in_val2, in_val3)
    

    In the first example the update does an index lookup. It has to, in order to update the right row. Oracle opens an implicit cursor, and we use it to wrap a corresponding insert so we know that the insert will only happen when the key does not exist. But the insert is an independent command and it has to do a second lookup. I don't know the inner workings of the merge command but since the command is a single unit, Oracle could have execute the correct insert or update with a single index lookup.

    I think merge is better when you do have some processing to be done that means taking data from some tables and updating a table, possibly inserting or deleting rows. But for the single row case, you may consider the first case since the syntax is more common.

    0 讨论(0)
提交回复
热议问题