Wiadomo (lub przynajmniej wiadomo), że nie można używać instrukcji DML w tabeli mutacji wewnątrz wyzwalacza. Fragment dokumentacji Oracle :
Tabela mutacji to tabela, która jest modyfikowana za pomocą instrukcji UPDATE, DELETE lub INSERT, lub tabela, która może być aktualizowana przez skutki ograniczenia DELETE CASCADE.
Sesja, która wydała instrukcję wyzwalającą, nie może zapytać ani zmodyfikować tabeli mutacji. To ograniczenie zapobiega wyświetlaniu przez wyzwalacz niespójnego zestawu danych.
Nie mogę jednak zrozumieć, dlaczego ten wyzwalacz demonstracyjny nie działa z błędem „mutating table”, gdy wykonuję program insert into emp
SQL Developer lub SQL * Plus:
CREATE OR REPLACE TRIGGER emp_bri
BEFORE INSERT ON emp
FOR EACH ROW
BEGIN
SELECT max(id) + 1 INTO :NEW.id FROM emp;
UPDATE emp SET salary = 5000;
END emp_bri;
Wstawianie kończy się pomyślnie kolejną id
wartością i aktualizuje wszystkie emp
rekordy. Korzystam z Oracle Database 11g Enterprise Edition Release 11.2.0.1.0. Czytałem o wyzwalaczach złożonych, ale próbka ich nie używa.
źródło
select max(id)
do przypisywania unikalnych numerów. Po prostu nie. Jest to po prostu niepoprawne i nie będzie również skalowane.Odpowiedzi:
Jest wyjątek. Po zdefiniowaniu
before insert
wyzwalacza na poziomie wiersza w tabeli i wydaniuINSERT
instrukcji z jednym wierszemtable is mutating
błąd nie zostanie zgłoszony. Ale jeśli zdefiniujesz ten sam rodzaj wyzwalacza i wydaszINSERT
instrukcję zawierającą wiele wierszy , błąd zostanie zgłoszony. Oto przykład:Oto
insert
instrukcja jednorzędowa , która nie podniesie błędu tabeli mutacji:Oto instrukcja wstawiania zawierająca wiele wierszy, która podniesie błąd tabeli mutacji:
źródło
ID 132569.1
(ORA-4091 on BEFORE ROW TRIGGER with INSERT .. into SELECT statement
).