Generalnie nie można wymusić tego rodzaju ograniczenia w wyzwalaczu. Będziesz musiał użyć ograniczenia.
Problem, który napotkasz, jeśli spróbujesz użyć wyzwalacza, polega na tym, że zazwyczaj napotkasz wyjątek „tabela mutacji”. Ogólnie rzecz biorąc, wyzwalacz na poziomie wiersza w tabeli A (tj. properties
) nie może wykonać zapytania do tabeli A. Możesz obejść ten problem, tworząc pakiet, tworząc kolekcję w tym pakiecie, inicjując kolekcję w wyzwalaczu instrukcji before, zapisując klucze, które są wstawiane lub aktualizowane do kolekcji w wyzwalaczu na poziomie wiersza , a następnie iterowanie przez elementy kolekcji w wyzwalaczu instrukcji after i wydawanie odpowiedniego DML względem tabeli. Wiąże się to jednak z dużą ilością ruchomych elementów i dużą złożonością (chociaż złożoność jest zmniejszona, jeśli korzystasz z 11g i możesz zamiast tego użyć złożonego wyzwalacza).
Ponadto, jeśli spróbujesz użyć wyzwalacza, napotkasz problemy w środowiskach wielu użytkowników. Jeśli użytkownik A wstawi wiersz w jednej sesji, a użytkownik B wstawi zduplikowany wiersz w innej sesji przed zatwierdzeniem przez użytkownika A, żaden wyzwalacz sesji nie wykryje zduplikowanego wiersza. Potencjalnie można obejść ten problem, jawnie blokując wiersz w tabeli nadrzędnej w celu serializacji wstawek do tabeli (celowo, aby aplikacja działała wolniej i była mniej skalowalna). Ale ograniczenie byłoby znacznie bardziej wydajnym i praktycznym rozwiązaniem.
Biorąc to wszystko pod uwagę, jeśli wstawiasz tylko jeden wiersz za pomocą INSERT ... VALUES
składni i ogranicz się do jednej sesji, Twój wyzwalacz wydaje się działać
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'