Oracle
 sql >> Database >  >> RDS >> Oracle

Trigger per verificare la presenza di duplicati

Non è possibile, in generale, imporre questo tipo di vincolo in un trigger. Dovresti usare un vincolo.

Il problema che dovrai affrontare se provi a utilizzare un trigger è che generalmente incontrerai un'eccezione di "tabella mutante". In generale, un trigger a livello di riga nella tabella A (cioè properties ) non può eseguire query sulla tabella A. È possibile aggirare il problema creando un pacchetto, creando una raccolta in tale pacchetto, inizializzando la raccolta in un trigger di istruzione before, scrivendo le chiavi che vengono inserite o aggiornate nella raccolta in un trigger a livello di riga , quindi scorrere gli elementi della raccolta in un trigger di istruzione after ed emettere un DML appropriato sulla tabella. Questo, tuttavia, comporta un sacco di pezzi in movimento e un sacco di complessità (sebbene la complessità sia ridotta se sei su 11 ge puoi invece utilizzare un trigger composto).

Inoltre, se provi a utilizzare un trigger, riscontrerai problemi in ambienti multiutente. Se l'utente A inserisce una riga in una sessione e l'utente B inserisce una riga duplicata in una sessione diversa prima che l'utente A effettui il commit, nessuno dei due trigger di sessione rileverà la riga duplicata. È possibile aggirare potenzialmente questo tipo di problema bloccando in modo esplicito una riga nella tabella padre per serializzare gli inserimenti nella tabella (rendendo intenzionalmente l'applicazione più lenta e meno scalabile). Ma un vincolo sarebbe una soluzione molto più efficiente e pratica.

Detto questo, se esegui solo inserimenti a riga singola utilizzando INSERT ... VALUES sintassi e limitarti a una singola sessione, il tuo trigger sembra funzionare

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'