insert if not exists oracle

后端 未结 10 2067
天命终不由人
天命终不由人 2020-12-07 23:08

I need to be able to run an Oracle query which goes to insert a number of rows, but it also checks to see if a primary key exists and if it does, then it skips that insert.

相关标签:
10条回答
  • 2020-12-07 23:16

    This is an answer to the comment posted by erikkallen:

    You don't need a temp table. If you only have a few rows, (SELECT 1 FROM dual UNION SELECT 2 FROM dual) will do. Why would your example give ORA-0001? Wouldn't merge take the update lock on the index key and not continue until Sess1 has either committed or rolled back? – erikkallen

    Well, try it yourself and tell me whether you get the same error or not:

    SESS1:

    create table t1 (pk int primary key, i int);
    create table t11 (pk int primary key, i int);
    insert into t1 values(1, 1);
    insert into t11 values(2, 21);
    insert into t11 values(3, 31);
    commit;
    

    SESS2: insert into t1 values(2, 2);

    SESS1:

    MERGE INTO t1 d
    USING t11 s ON (d.pk = s.pk)
    WHEN NOT MATCHED THEN INSERT (d.pk, d.i) VALUES (s.pk, s.i);
    

    SESS2: commit;

    SESS1: ORA-00001

    0 讨论(0)
  • 2020-12-07 23:18

    We can combine the DUAL and NOT EXISTS to archive your requirement:

    INSERT INTO schema.myFoo ( 
        primary_key, value1, value2
    ) 
    SELECT
        'bar', 'baz', 'bat' 
    FROM DUAL
    WHERE NOT EXISTS (
        SELECT 1 
        FROM schema.myFoo
        WHERE primary_key = 'bar'
    );
    
    0 讨论(0)
  • 2020-12-07 23:20

    INSERT INTO schema.myFoo ( primary_key        , value1          , value2         )
                             SELECT 'bar1' AS primary_key ,'baz1' AS value1 ,'bat1' AS value2 FROM DUAL WHERE (SELECT 1 AS value FROM schema.myFoo WHERE LOWER(primary_key) ='bar1' AND ROWNUM=1) is null;
    

    0 讨论(0)
  • 2020-12-07 23:26

    If your table is "independent" from others (I mean, it will not trigger a cascade delete or will not set any foreign keys relations to null), a nice trick could be to first DELETE the row and then INSERT it again. It could go like this:

    DELETE FROM MyTable WHERE prop1 = 'aaa'; //assuming it will select at most one row!

    INSERT INTO MyTable (prop1, ...) VALUES ('aaa', ...);

    If your are deleting something which does not exist, nothing will happen.

    0 讨论(0)
  • 2020-12-07 23:28
    DECLARE
       tmp NUMBER(3,1);
    BEGIN
      SELECT COUNT(content_id) INTO tmp FROM contents WHERE (condition);
      if tmp != 0 then
        INSERT INTO contents VALUES (...);
      else
        INSERT INTO contents VALUES (...);
      end if;
    END;
    

    I used the code above. It is long, but, simple and worked for me. Similar, to Micheal's code.

    0 讨论(0)
  • 2020-12-07 23:36

    Coming late to the party, but...

    With oracle 11.2.0.1 there is a semantic hint that can do this: IGNORE_ROW_ON_DUPKEY_INDEX

    Example:

    insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(customer_orders,pk_customer_orders) */
      into customer_orders
           (order_id, customer, product)
    values (    1234,     9876,  'K598')
         ;
    

    UPDATE: Although this hint works (if you spell it correctly), there are better approaches which don't require Oracle 11R2:

    First approach—direct translation of above semantic hint:

    begin
      insert into customer_orders
             (order_id, customer, product)
      values (    1234,     9876,  'K698')
      ;
      commit;
    exception
      when DUP_VAL_ON_INDEX
      then ROLLBACK;
    end;
    

    Second aproach—a lot faster than both above hints when there's a lot of contention:

    begin
        select count (*)
        into   l_is_matching_row
        from   customer_orders
        where  order_id = 1234
        ;
    
        if (l_is_matching_row = 0)
        then
          insert into customer_orders
                 (order_id, customer, product)
          values (    1234,     9876,  'K698')
          ;
          commit;
        end if;
    exception
      when DUP_VAL_ON_INDEX
      then ROLLBACK;
    end;
    
    0 讨论(0)
提交回复
热议问题