oracle sql:如果存在则更新,否则插入

时间:2010-10-25 13:50:27

标签: sql oracle

  

可能重复:
  Oracle: how to UPSERT (update or insert into a table?)

您好,

我有一个表,如果记录已经存在,则必须修改记录,否则必须插入新记录。 Oracle sql不接受IF EXISTS,否则我会进行if - update - else - insert查询。我查看了MERGE但它只适用于多个表。我该怎么办?

6 个答案:

答案 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)然后决定是否插入或更新,在客户端解决问题。