插入如果不存在oracle

cwa*_*ole 42 sql oracle oracle-sqldeveloper

我需要能够运行Oracle查询,该查询将插入多个行,但它还会检查是否存在主键,如果存在,则会跳过该插入.就像是:

INSERT ALL
    IF NOT EXISTS( SELECT 1 WHERE fo.primary_key='bar' )
    (
        INSERT INTO 
            schema.myFoo fo ( primary_key, value1, value2 )
        VALUES
            ('bar','baz','bat')
    ),

    IF NOT EXISTS( SELECT 1 WHERE fo.primary_key='bar1' )
    (
        INSERT INTO 
            schema.myFoo fo ( primary_key, value1, value2 )
        VALUES
            ('bar1','baz1','bat1')
    )
SELECT * FROM schema.myFoo;
Run Code Online (Sandbox Code Playgroud)

Oracle完全可以实现这一点吗?

如果您可以告诉我如何在PostgreSQL或MySQL中执行此操作,可以获得奖励积分.

Mic*_*uff 37

迟到了,但......

使用oracle 11.2.0.1,有一个语义提示可以执行此操作:IGNORE_ROW_ON_DUPKEY_INDEX

例:

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

更新:尽管此提示有效(如果拼写正确),但有更好的方法不需要Oracle 11R2:

第一种方法 - 直接翻译上述语义提示:

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

其次的形式给出,一个很多比上面的时候有很多争论的双方提示更快:

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;
Run Code Online (Sandbox Code Playgroud)


eri*_*len 24

该声明称为MERGE.抬起头来,我太懒了.

但要注意,MERGE不是原子的,这可能会导致以下影响(谢谢,Marius):

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;
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)

SESS2: commit;

SESS1: ORA-00001


小智 18

仅当要插入的项目尚未存在时才会插入.

作用相同:

if not exists (...) insert ... 
Run Code Online (Sandbox Code Playgroud)

在T-SQL中

insert into destination (DESTINATIONABBREV) 
  select 'xyz' from dual 
  left outer join destination d on d.destinationabbrev = 'xyz' 
  where d.destinationid is null;
Run Code Online (Sandbox Code Playgroud)

可能不漂亮,但它很方便:)

  • 或类似的,with exists:`insert into destination select'id','xyz'from dual where not exists(select id from destination from id ='id')` (13认同)

Ray*_*hiu 11

我们可以将DUAL和NOT EXISTS结合起来存档您的要求:

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'
);
Run Code Online (Sandbox Code Playgroud)


小智 10

如果你不想从其他表合并,而是插入新数据......我想出了这个.有没有更好的方法来做到这一点?

MERGE INTO TABLE1 a
    USING DUAL
    ON (a.C1_pk= 6)
WHEN NOT MATCHED THEN
    INSERT(C1_pk, C2,C3,C4)
    VALUES (6, 1,0,1);
Run Code Online (Sandbox Code Playgroud)


use*_*019 5

它代码在客户端,然后你有许多访问服务器,以消除它.

将所有数据插入到临时表中,表示T与myFoo具有相同的结构

然后

insert myFoo
  select *
     from t
       where t.primary_key not in ( select primary_key from myFoo) 
Run Code Online (Sandbox Code Playgroud)

这应该适用于其他数据库 - 我在Sybase上完成了这项工作

如果您通过线路复制了所有数据,那么插入新数据的次数并不是最好的.