Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Como contornar uma violação de restrição única?


Uma opção seria usar instead of acionar. No entanto, esta solução requer que você renomeie suas tabelas e crie visualizações com os nomes que elas tinham. Dessa forma, você não afeta a lógica do aplicativo, mas pode afetar o desempenho geral, portanto, deve ser testado adequadamente.

No entanto, usar gatilhos para alterar a lógica errada do aplicativo não é uma boa ideia. Entendo sua situação de que às vezes precisamos encontrar soluções alternativas para problemas existentes, mas isso não resolve.

Enfim, abaixo um exemplo simples que você pode aplicar na sua lógica
SQL> create table t ( c1 number primary key , c2 varchar2(1) ) ;

Table created.

SQL> alter table t rename to tbl_t ;

Table altered.

SQL>  create view t as ( select c1 , c2 from tbl_t ) ;

View created.

Agora criamos um instead of acionar
SQL> create or replace trigger tr_v_t
  2  instead of insert
  3  on t
  4  for each row
  5  declare
  6    pk_violation_exception exception;
  7    pragma exception_init(pk_violation_exception, -00001);
  8  begin
  9    insert into tbl_t (c1,c2)
 10    values ( :new.c1,:new.c2 );
 11    exception
 12      when pk_violation_exception then
 13        dbms_output.put_line('ora-00001 (pk_violation_exception) captured');
 14        update tbl_t
 15        set c2   = :new.c2
 16        where c1 = :new.c1 ;
 17* end;
SQL> /

Trigger created.

Com este gatilho, qualquer tentativa de violação da restrição possibilitará a atualização do valor na tabela final.
SQL> select * from t ;

no rows selected

SQL> insert into t values ( 1 , 'A' ) ;

1 row created.

SQL> commit ;

Commit complete.

SQL> insert into t values ( 2, 'B' ) ;

1 row created.

SQL> commit ;

Commit complete.

SQL> insert into t values ( 2, 'C' ) ;
ORA-00001 (pk_violation_exception) captured

1 row created.

SQL> select * from tbl_t ;

        C1 C
---------- -
         1 A
         2 C