¿Cómo UPSERT (actualizar o insertar en una tabla?)

Resuelto Mark Harrison asked hace 16 años • 11 respuestas

La operación UPSERT actualiza o inserta una fila en una tabla, dependiendo de si la tabla ya tiene una fila que coincide con los datos:

if table t has a row exists that has key X:
    update t set mystuff... where mykey=X
else
    insert into t mystuff...

Dado que Oracle no tiene una declaración UPSERT específica, ¿cuál es la mejor manera de hacerlo?

Mark Harrison avatar Oct 26 '08 08:10 Mark Harrison
Aceptado

La declaración MERGE fusiona datos entre dos tablas. Usar DUAL nos permite usar este comando. Tenga en cuenta que esto no está protegido contra el acceso simultáneo.

create or replace
procedure ups(xa number)
as
begin
    merge into mergetest m using dual on (a = xa)
         when not matched then insert (a,b) values (xa,1)
             when matched then update set b = b+1;
end ups;
/
drop table mergetest;
create table mergetest(a number, b number);
call ups(10);
call ups(10);
call ups(20);
select * from mergetest;

A                      B
---------------------- ----------------------
10                     2
20                     1
Mark Harrison avatar Oct 26 '2008 01:10 Mark Harrison

El ejemplo dual anterior, que está en PL/SQL, fue excelente porque quería hacer algo similar, pero lo quería del lado del cliente... así que aquí está el SQL que usé para enviar una declaración similar directamente desde C#.

MERGE INTO Employee USING dual ON ( "id"=2097153 )
WHEN MATCHED THEN UPDATE SET "last"="smith" , "name"="john"
WHEN NOT MATCHED THEN INSERT ("id","last","name") 
    VALUES ( 2097153,"smith", "john" )

Sin embargo, desde una perspectiva de C#, esto resulta ser más lento que realizar la actualización y ver si las filas afectadas eran 0 y realizar la inserción si lo fuera.

MyDeveloperDay avatar Apr 22 '2010 16:04 MyDeveloperDay

Una alternativa a MERGE (la "forma antigua"):

begin
   insert into t (mykey, mystuff) 
      values ('X', 123);
exception
   when dup_val_on_index then
      update t 
      set    mystuff = 123 
      where  mykey = 'X';
end;   
Tony Andrews avatar Oct 27 '2008 11:10 Tony Andrews