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

Acionador para verificar se há duplicatas


Você não pode, em geral, impor esse tipo de restrição em um gatilho. Você precisaria usar uma restrição.

O problema que você enfrentará se tentar usar um gatilho é que geralmente encontrará uma exceção de "tabela de mutação". Em geral, um gatilho em nível de linha na tabela A (ou seja, properties ) não pode consultar a tabela A. Você pode contornar esse problema criando um pacote, criando uma coleção nesse pacote, inicializando a coleção em um gatilho de instrução antes, gravando as chaves que são inseridas ou atualizadas na coleção em um gatilho de nível de linha e, em seguida, iterando pelos elementos da coleção em um gatilho de instrução after e emitindo DML apropriado na tabela. Isso, no entanto, envolve muitas peças em movimento e muita complexidade (embora a complexidade seja reduzida se você estiver no 11g e puder usar um gatilho composto).

Além disso, se você tentar usar um gatilho, encontrará problemas em ambientes multiusuário. Se o usuário A inserir uma linha em uma sessão e o usuário B inserir uma linha duplicada em uma sessão diferente antes de o usuário A confirmar, nenhum gatilho da sessão detectará a linha duplicada. Você pode contornar esse tipo de problema bloqueando explicitamente uma linha na tabela pai para serializar inserções na tabela (intencionalmente tornando o aplicativo mais lento e menos escalável). Mas uma restrição seria uma solução muito mais eficiente e prática.

Tudo o que foi dito, se você fizer apenas inserções de linha única usando o INSERT ... VALUES sintaxe e restringir-se a uma única sessão, seu gatilho parece funcionar
SQL> ed
Wrote file afiedt.buf

  1  create table Properties(
  2          idProperties number(10) NOT NULL,
  3          Address_FK number(20),
  4          Ownership_FK number(20)
  5* )
SQL> /

Table created.

SQL> CREATE OR REPLACE TRIGGER Check_Duplicate
  2  before insert or update on properties
  3  FOR each ROW
  4
  5  declare
  6  v_dup number;
  7
  8  begin
  9      select count(idProperties) INTO v_dup from properties where Address_FK=
:NEW.Address_FK and
 10       Ownership_FK=:NEW.Ownership_FK;
 11
 12   if v_dup > 0 then
 13     Raise_Application_Error (-20100, 'This property already exists. The inse
rt is cancelled.');
 14  end if;
 15  end;
 16  /

Trigger created.

SQL> insert into properties values( 1, 10, 100 );

1 row created.

SQL> insert into properties values( 2, 10, 100 );
insert into properties values( 2, 10, 100 )
            *
ERROR at line 1:
ORA-20100: This property already exists. The insert is cancelled.
ORA-06512: at "SCOTT.CHECK_DUPLICATE", line 9
ORA-04088: error during execution of trigger 'SCOTT.CHECK_DUPLICATE'