我需要能够运行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;
Oracle完全可以实现这一点吗?
如果您可以告诉我如何在PostgreSQL或MySQL中执行此操作,可以获得奖励积分 .
10 回答
该声明称为MERGE . 抬起头来,我太懒了 .
但要注意,MERGE不是原子的,这可能会导致以下影响(谢谢,Marius):
SESS1:
SESS2:
insert into t1 values(2, 2);
SESS1:
SESS2:
commit;
SESS1:
ORA-00001
迟到了,但......
使用oracle 11.2.0.1,有一个语义提示可以执行此操作: IGNORE_ROW_ON_DUPKEY_INDEX
例:
UPDATE :虽然这个提示有效(如果拼写正确),但better approaches不需要Oracle 11R2:
第一种方法 - 直接翻译上述语义提示:
第二个方法 - 比以上两个提示要快得多:
仅当要插入的项目尚未存在时才会插入 .
作用相同:
在T-SQL中
可能不漂亮,但它很方便:)
我们可以将DUAL和NOT EXISTS结合起来存档您的要求:
如果你不想从其他表合并,而是插入新数据......我想出了这个 . 有没有更好的方法来做到这一点?
它代码在客户端,然后你有许多访问服务器,以消除它 .
将所有数据插入到临时表中,表示T与myFoo具有相同的结构
然后
这应该适用于其他数据库 - 我在Sybase上完成了这项工作
如果您通过线路复制了所有数据,那么插入新数据的次数并不是最好的 .
我用过上面的代码 . 这很长,但是,简单而且适合我 . 类似于Micheal的代码 .
这是对erikkallen发表的评论的回答:
好吧,亲自试试并告诉我你是否得到同样的错误:
SESS1:
SESS2:
insert into t1 values(2, 2);
SESS1:
SESS2:
commit;
SESS1:
ORA-00001
如果你的表与其他人“独立”(我的意思是,它不会触发级联删除或不会将任何外键关系设置为null),一个很好的技巧可能是首先删除该行然后再次插入它 . 它可能是这样的:
DELETE FROM MyTable WHERE prop1 ='aaa'; //假设它最多会选择一行!
INSERT INTO MyTable(prop1,...)VALUES('aaa',...);
如果您要删除不存在的内容,则不会发生任何事情 .