Materiały dydaktyczne do zajęć o wyzwalaczach

Zadanie

Napisać wyzwalacze, które zapewnią realizację opcji ON DELETE SET NULL i ON UPDATE CASCADE na przykładowych tabelach dla klucza obcego b2 w tabeli b.

Przypominam, że obecnie w Oracle obie te opcje sa niedostępne.

Rozwiązanie

Oto możliwe kolejne fazy prac prowadzących do rozwiązania tego zadania.

trigger1.sql
Tu nie ma wyzwalaczy. DELETE nie powiedzie się, bo domyślnie jest ON DELETE RESTRICT. Moglibyśmy dodać ON DELETE CASCADE do więzów klucza obcego (tak jak w trigger1a.sql), ale nam przecież chodzi o ON DELETE SET NULL.
trigger2.sql
Tu jest już odpowiedni wyzwalacz dla ON DELETE SET NULL, ale nie będzie dzialał ze względu na bardzo zachłanny mechanizm zamków w Oracle. Wykonanie operacji na tabeli powoduje zablokowanie tej tabeli (tu A) i wszystkich tabel do niej się odwołujących (tu B). DELETE nie powiedzie się, bo w trakcie wykonywania wyzwalacza zablokowana jest również tabela B.
trigger3.sql
Żeby tego uniknąć należy usunąć więzy spójności referencyjnej (REFERENCES A). Teraz wyzwalacz działa, ale spójność referencyjna nie jest sprawdzana...
trigger4.sql
Dodaliśmy wyzwalacz pilnujący spójności referencyjnej. To działa, dlatego, że w tym wyzwalaczu sprawdzamy, czy :new.b2 nie jest przypadkiem NULL.
trigger5.sql
Naiwna próba dodania wyzwalacza realizującego ON UPDATE CASCADE. To nie działa, bo wykonanie UPDATE na A, wzbudza wyzwalacz OnUpdCascade, który wykonując UPDATE na B wzbudza wyzwalacz OnInsertOrUpdCheck, który z kolei próbuje wykonać SELECT na A, co kończy się błędem, bo A jest w tej chwili zablokowana.
trigger6.sql
Ostateczne rozwiązanie. Dodajemy pakiet ze zmienną enabled, którą odczytuje (przez wywołanie funkcji is_enabled) wyzwalacz OnInsertOrUpdCheck i z jej wartości wnioskuje czy ma wykonać sprawdzenie, czy nie. Nie wykonuje sprawdzenia jedynie w czasie działania OnUpdCascade, ale wtedy wiemy, że ten właśnie wyzwalacz dba o spójność bazy danych (jest wiarygodny i nie musimy sprawdzać wyników jego działania).