Recuerda que en las ciencias informáticas un error casi siempere puede tener más de una resoluciones, por lo tanto nosotros aquí te enseñaremos lo más óptimo y eficiente.
Solución:
Llegar tarde a la fiesta, pero…
Con Oracle 11.2.0.1 hay un pista semántica que puede hacer esto: IGNORE_ROW_ON_DUPKEY_INDEX
Ejemplo:
insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(customer_orders,pk_customer_orders) */
into customer_orders
(order_id, customer, product)
values ( 1234, 9876, 'K598')
;
ACTUALIZAR: aunque esta sugerencia funciona (si la deletrea correctamente), hay mejores enfoques que no requieren Oracle 11R2:
Primer enfoque: traducción directa de la sugerencia semántica anterior:
begin
insert into customer_orders
(order_id, customer, product)
values ( 1234, 9876, 'K698')
;
commit;
exception
when DUP_VAL_ON_INDEX
then ROLLBACK;
end;
Segundo enfoque: un lote más rápido que las dos sugerencias anteriores cuando hay mucha disputa:
begin
select count (*)
into l_is_matching_row
from customer_orders
where order_id = 1234
;
if (l_is_matching_row = 0)
then
insert into customer_orders
(order_id, customer, product)
values ( 1234, 9876, 'K698')
;
commit;
end if;
exception
when DUP_VAL_ON_INDEX
then ROLLBACK;
end;
La sentencia se llama MERGE. Búscalo, soy demasiado perezoso.
Sin embargo, tenga en cuenta que MERGE no es atómico, lo que podría causar el siguiente efecto (gracias, Marius):
SESS1:
create table t1 (pk int primary key, i int);
create table t11 (pk int primary key, i int);
insert into t1 values(1, 1);
insert into t11 values(2, 21);
insert into t11 values(3, 31);
commit;
SES2: insert into t1 values(2, 2);
SESS1:
MERGE INTO t1 d
USING t11 s ON (d.pk = s.pk)
WHEN NOT MATCHED THEN INSERT (d.pk, d.i) VALUES (s.pk, s.i);
SES2: commit;
SESS1: ORA-00001
Esto solo se inserta si el elemento que se va a insertar aún no está presente.
Funciona igual que:
if not exists (...) insert ...
en TSQL
insert into destination (DESTINATIONABBREV)
select 'xyz' from dual
left outer join destination d on d.destinationabbrev = 'xyz'
where d.destinationid is null;
Puede que no sea bonito, pero es útil 🙂
Acuérdate de que tienes el privilegio decir .