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'