Oracle 如果不存在则插入
我需要能够运行一个 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 中执行此操作,我会加分。
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. Something like:
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;
Is this at all possible with Oracle?
Bonus points if you can tell me how to do this in PostgreSQL or MySQL.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
来晚了,但是...
在 oracle 11.2.0.1 中,有一个语义提示可以做到这一点:IGNORE_ROW_ON_DUPKEY_INDEX
示例:
UPDATE :虽然这个提示有效(如果你拼写正确的话),但是还有更好的不需要 Oracle 11R2 的方法:
第一种方法 - 直接翻译上述语义提示:
第二种方法 - 当存在大量争用时,比上述两种提示快很多:
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:
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:
Second aproach—a lot faster than both above hints when there's a lot of contention:
该语句称为 MERGE。看看吧,我太懒了。
但请注意,MERGE 不是原子的,这可能会导致以下效果(谢谢 Marius):
SESS1:
SESS2:
insert into t1 values(2, 2);
SESS1:
SESS2:
提交;
SESS1:
ORA-00001
The statement is called MERGE. Look it up, I'm too lazy.
Beware, though, that MERGE is not atomic, which could cause the following effect (thanks, Marius):
SESS1:
SESS2:
insert into t1 values(2, 2);
SESS1:
SESS2:
commit;
SESS1:
ORA-00001
我们可以结合
DUAL
和NOT EXISTS
来实现您的要求:We can combine the
DUAL
andNOT EXISTS
to achieve your requirement:仅当要插入的项目尚不存在时才会插入。
工作原理与:
在 T-SQL 中
可能不太漂亮,但很方便:)
This only inserts if the item to be inserted is not already present.
Works the same as:
in T-SQL
may not be pretty, but it's handy :)
如果您不想从其他表合并,而是插入新数据......我想出了这个。也许有更好的方法来做到这一点吗?
If you do NOT want to merge in from an other table, but rather insert new data... I came up with this. Is there perhaps a better way to do this?
如果代码位于客户端,那么您需要多次访问服务器,以便消除这种情况。
将所有数据插入到一个临时表中,比如 T ,其结构与 myFoo 相同
然后
这也应该适用于其他数据库 - 我已经在 Sybase 上完成了这一点
如果要像您一样插入很少的新数据,那不是最好的已通过网络复制了所有数据。
It that code is on the client then you have many trips to the server so to eliminate that.
Insert all the data into a temportary table say T with the same structure as myFoo
Then
This should work on other databases as well - I have done this on Sybase
It is not the best if very few of the new data is to be inserted as you have copied all the data over the wire.
我使用了上面的代码。它很长,但是很简单并且对我有用。与迈克尔的代码类似。
I used the code above. It is long, but, simple and worked for me. Similar, to Micheal's code.
如果您的表与其他表“独立”(我的意思是,它不会触发级联删除或不会将任何外键关系设置为空),一个不错的技巧可能是首先删除该行,然后再次插入它。它可以像这样:
DELETE FROM MyTable WHERE prop1 = 'aaa'; //假设它最多选择一行!
INSERT INTO MyTable (prop1, ...) VALUES ('aaa', ...);
如果您要删除不存在的内容,则不会发生任何事情。
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.
这是对 erikkallen 发表的评论的回答:
好吧,你自己尝试一下,然后告诉我你是否遇到同样的错误:
SESS1:
SESS2:
insert into t1 value(2, 2);
SESS1:
SESS2:
commit;< /代码>
SESS1:<代码>ORA-00001
This is an answer to the comment posted by erikkallen:
Well, try it yourself and tell me whether you get the same error or not:
SESS1:
SESS2:
insert into t1 values(2, 2);
SESS1:
SESS2:
commit;
SESS1:
ORA-00001