可能重复:
Oracle: how to UPSERT (update or insert into a table?)
您好,
我有一个表,如果记录已经存在,则必须修改记录,否则必须插入新记录。
Oracle sql不接受IF EXISTS
,否则我会进行if - update - else - insert
查询。我查看了MERGE
但它只适用于多个表。我该怎么办?
答案 0 :(得分:55)
MERGE不需要“多个表”,但确实需要查询作为源。这样的事情应该有效:
MERGE INTO mytable d
USING (SELECT 1 id, 'x' name from dual) s
ON (d.id = s.id)
WHEN MATCHED THEN UPDATE SET d.name = s.name
WHEN NOT MATCHED THEN INSERT (id, name) VALUES (s.id, s.name);
或者你可以在PL / SQL中执行此操作:
BEGIN
INSERT INTO mytable (id, name) VALUES (1, 'x');
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
UPDATE mytable
SET name = 'x'
WHERE id = 1;
END;
答案 1 :(得分:5)
您可以使用SQL%ROWCOUNT
Oracle变量:
UPDATE table1
SET field2 = value2,
field3 = value3
WHERE field1 = value1;
IF (SQL%ROWCOUNT = 0) THEN
INSERT INTO table (field1, field2, field3)
VALUES (value1, value2, value3);
END IF;
确定您的主键(即field1
)是否具有值然后执行相应的插入或更新会更容易。也就是说,如果您将所述值用作存储过程的参数。
答案 2 :(得分:5)
merge into MY_TABLE tgt
using (select [expressions]
from dual ) src
on (src.key_condition = tgt.key_condition)
when matched then
update tgt
set tgt.column1 = src.column1 [,...]
when not matched then
insert into tgt
([list of columns])
values
(src.column1 [,...]);
答案 3 :(得分:2)
我总是这样做(假设数据永远不会被删除,只插入)是
insert
,如果此操作因唯一约束违规而失败,那么您知道该行就在那里,update
不幸的是,许多框架(如Hibernate)将所有数据库错误(例如,唯一约束违规)视为不可恢复的条件,因此并不总是那么容易。 (在Hibernate中,解决方案是打开一个新的会话/事务,只是为了执行这一个insert
命令。)
即使返回零,您也不能只执行select count(*) .. where ..
,因此您选择在执行insert
和{{select
之间执行insert
1}}其他人可能会insert
编辑该行,因此您的insert
将会失败。
答案 4 :(得分:0)
HC-way:)
DECLARE
rt_mytable mytable%ROWTYPE;
CURSOR update_mytable_cursor(p_rt_mytable IN mytable%ROWTYPE) IS
SELECT *
FROM mytable
WHERE ID = p_rt_mytable.ID
FOR UPDATE;
BEGIN
rt_mytable.ID := 1;
rt_mytable.NAME := 'x';
INSERT INTO mytable VALUES (rt_mytable);
EXCEPTION WHEN DUP_VAL_ON_INDEX THEN
<<update_mytable>>
FOR i IN update_mytable_cursor(rt_mytable) LOOP
UPDATE mytable SET
NAME = p_rt_mytable.NAME
WHERE CURRENT OF update_mytable_cursor;
END LOOP update_mytable;
END;
答案 5 :(得分:-1)
如果要在Oracle中使用UPSERT / MERGE命令,请参阅this问题。否则,只需首先执行count(1)
然后决定是否插入或更新,在客户端解决问题。