Wyzwalacze Wyzwalacze s ˛a specjalnymi procedurami
Transkrypt
Wyzwalacze Wyzwalacze s ˛a specjalnymi procedurami
Wyzwalacze Wyzwalacze sa˛ specjalnymi procedurami składowanymi, uruchamianymi automatycznie w nast˛epstwie zaistnienia określonego typu zdarzenia. Ich główne zadanie polega na wymuszaniu integralności danych i zapewnienie, aby dane przechowywane w bazie były zgodne z regułami narzuconymi przed projektanta bazy. Każdy wyzwalacz jest zwiazany ˛ z określona˛ tabela˛ (lub widokiem) i jest uruchamiany w nast˛epstwie zajścia jednego z trzech zdarzeń: wywołanie instrukcji INSERT, UPDATE lub DELETE dla danej tabeli (widoku). Dodatkowo, można określić kiedy wyzwalacz ma zostać uruchomiony: przed zdarzeniem (wyzwalacz typu BEFORE), po zdarzeniu (AFTER) lub zamiast zdarzenia (INSTEAD OF) (ten typ wyzwalaczy stosujemy do widoków). Składnia instrukcji tworzacej ˛ wyzwalacz CREATE OR REPLACE TRIGGER nazwa BEFORE / AFTER / INSTEAD OF INSERT / UPDATE / DELETE OR kolejne zdarzenie ON tabela/widok FOR EACH ROW ciało wyzwalacza Za pomoca˛ wyzwalaczy można zrealizować wiele istotnych, z punktu widzenia integralności i bezpieczeństwa danych, zadań, m.in. ◮ zapewnienie integralności danych; ◮ sprawdzanie reguł poprawności wstawianych (modyfikowanych) danych; ◮ logowanie zdarzeń w systemie; można stworzyć własna˛ tabel˛e z logami, a nast˛epnie wyzwalacze, które b˛eda˛ do tej tabeli wstawiać kolejne wiersze w odpowiedzi na działania na obiektach bazy danych; ◮ modyfikowanie danych, które maja˛ zostać wstawione do tabeli (np. odpowiednie formatowanie) przed ich umieszczeniem w tabeli; ◮ automatyczne generowanie treści, np. obsługa pól auto increment, w szczególności, można wykorzystać wyzwalacz w połaczeniu ˛ z sekwencja˛ do automatycznego generowania wartości kluczy głównych. Składnia instrukcji tworzacej ˛ wyzwalacz CREATE OR REPLACE TRIGGER nazwa BEFORE / AFTER / INSTEAD OF INSERT / UPDATE / DELETE OR kolejne zdarzenie ON tabela/widok FOR EACH ROW ciało wyzwalacza Opis opcji definicji: •Wybieramy jedna˛ z opcji BEFORE / AFTER / INSTEAD OF aby określić, kiedy wyzwalacz ma zostać uruchomiony. ◮ przed zdarzeniem (wyzwalacz typu BEFORE), ◮ po zdarzeniu (AFTER), ◮ zamiast zdarzenia (INSTEAD OF) (ten typ wyzwalaczy stosujemy do widoków). Składnia instrukcji tworzacej ˛ wyzwalacz CREATE OR REPLACE TRIGGER nazwa BEFORE / AFTER / INSTEAD OF INSERT / UPDATE / DELETE OR kolejne zdarzenie ON tabela/widok FOR EACH ROW ciało wyzwalacza Opis opcji definicji: •Wybieramy jedna˛ z opcji BEFORE / AFTER / INSTEAD OF aby określić, kiedy wyzwalacz ma zostać uruchomiony. •Określamy, dla którego ze zdarzeń INSERT / UPDATE / DELETE wyzwalacz ma zostać zdefiniowany. Jeden wyzwalacz może zostać zdefiniowany dla kilku zdarzeń. Składnia instrukcji tworzacej ˛ wyzwalacz CREATE OR REPLACE TRIGGER nazwa BEFORE / AFTER / INSTEAD OF INSERT / UPDATE / DELETE OR kolejne zdarzenie ON tabela/widok FOR EACH ROW ciało wyzwalacza Opis opcji definicji: •Wybieramy jedna˛ z opcji BEFORE / AFTER / INSTEAD OF aby określić, kiedy wyzwalacz ma zostać uruchomiony. •Określamy, dla którego ze zdarzeń INSERT / UPDATE / DELETE wyzwalacz ma zostać zdefiniowany. Jeden wyzwalacz może zostać zdefiniowany dla kilku zdarzeń. •W klauzuli ON określamy tabel˛e lub widok. Wyzwalacze na poziomie wiersza lub instrukcji Kwalifikatory new i old w wyzwalaczach wierszowych W ciele wyzwalacza można korzystać ze wszystkich instrukcji, które sa˛ dost˛epne dla procedur zapami˛etanych. Dwa typy wyzwalaczy: ◮ typu ROW — działajace ˛ na poziomie wiersza (wierszowe), które definiujemy za pomoca˛ klauzuli FOR EACH ROW, ◮ działajace ˛ na poziomie instrukcji (opcja domyślna). Wyzwalacz wierszowy jest uruchamiany dla każdego wiersza, na którym operuje instrukcja DML, wyzwalacz zdefiniowany na poziomie instrukcji jest uruchamiany raz w odpowiedzi na instrukcj˛e. np. w przypadku aktualizacji 10 wierszy, wyzwalacz typu ROW b˛edzie uruchamiany 10 razy. W wyzwalaczach wierszowych mamy dodatkowo dost˛epne dwa kwalifikatory new oraz old, które pozwalaja˛ odwoływać si˛e odpowiednio do nowych lub poprzednich wartości pól wstawianego lub usuwanego czy modyfikowanego wiersza. Uwaga. Dla wyzwalaczy uruchamianych w nast˛epstwie wykonania instrukcji INSERT mamy dost˛epne tylko wartości new, dla wyzwalaczy dla DELETE — tylko wartości old, natomiast w przypadku zdarzenia UPDATE — dost˛epne sa˛ obie wartości. Dla przykładu, jeżeli mamy zdefiniowany wyzwalacz wierszowy dla tabeli employee, dla zdarzenia UPDATE, to aby odwołać si˛e do poprzedniej wartości zarobków w modyfikowanym wierszu, należy użyć składni :old.salary, natomiast aby odczytać nowa˛ wartość zarobków, należy użyć odwołania :new.salary. Wyzwalacze działajace ˛ dla kilku zdarzeń DML Uwaga. W ciele wyzwalacza nie może być instrukcji, które ◮ modyfikuja˛ struktur˛e tabeli, na która˛ nałożony jest wyzwalacz; ◮ modyfikuja˛ dane w tabeli, dla której zdefiniowany jest dany wyzwalacz; ◮ wpływaja˛ na transakcj˛e; ◮ odowłuja˛ si˛e do podprogramów (procedur, funkcji), które zawieraja˛ takie instrukcje. Stosowanie predykatów INSERTING, UPDATING, DELETING Czasem wygodnie jest mieć wyzwalacz, który jest wywoływany w odpowiedzi na zajście wi˛ecej niż jednego ze zdarzeń INSERT, UPDATE, DELETE. Jeżeli mamy taki wyzwalacz, to musimy mieć możliwość sprawdzić, które zdarzenie wywołało ten wyzwalacz. W tym celu można użyć predykatów INSERTING, UPDATING, DELETING. Predykatów można użyć np. w warunku instrukcji IF, aby móc wykonać różne operacje, w zależności od tego, jaka instrukcja została wykonana, np. IF INSERTING THEN ... ELSIF UPDATING THEN ... ELSIF DELETING THEN ... END IF; Jeden wyzwalacz może zostać zdefiniowany dla kilku zdarzeń, np. aby zdefiniować wyzwalacz wierszowy dla tabeli employee, wywoływany po instrukcji UPDATE lub INSERT, użyjemy składni: CREATE OR REPLACE TRIGGER nowy AFTER INSERT OR UPDATE ON employee FOR EACH ROW ... Zarzadzanie ˛ wyzwalaczami ◮ Do usuwania wyzwalaczy służy instrukcja DROP TRIGGER nazwa. Cz˛esto nie chcemy usuwać wyzwalacza, a jedynie go czasowo dezaktywować (wyzwalacze wydłużaja˛ czas wykonywania modyfikacji, jeżeli planujemy przeprowadzić duża˛ liczb˛e instrukcji DML, aby przyspieszyć działanie, można przedtem wyłaczyć ˛ pewne wyzwalacze). ◮ Wyzwalacz wyłaczamy ˛ instrukcja˛ ALTER TRIGGER nazwa DISABLE. ◮ Aby ponownie aktywować wyzwalacz, należy użyć instrukcji ALTER TRIGGER nazwa ENABLE. ◮ Dla jednej tabeli może być zdefiniowanych kilka wyzwalaczy tego samego typu. Sa˛ one wówczas uruchamiane sekwencyjnie. Sekwencje Uwaga. Od wersji 11g bazy Oracle, można użyć klauzuli FOLLOWS w definicji wyzwalacza, aby określić kolejność wykonywania wyzwalaczy tego samego typu: CREATE OR REPLACE TRIGGER nowy1 AFTER INSERT ON employee FOR EACH ROW FOLLOWS nowy ... Sekwencje w bazie Oracle to mechanizmy umożliwiajace ˛ generowanie kolejnych wartości liczbowych. Instrukcja tworzaca ˛ sekwencj˛e: CREATE SEQUENCE nazwa INCREMENT BY liczba START WITH liczba Znaczenie opcji INCREMENT BY liczba — skok sekwencji (domyślnie 1), START WITH liczba — wartość poczatkowa ˛ (domyślnie 1). Metody sekwencji: CURRVAL — pobranie bieżacej ˛ wartości, NEXTVAL — pobranie nast˛epnej wartości. Sekwencje Definiujemy sekwencj˛e dla klucza głównego emp_no tabeli employee: CREATE SEQUENCE emp_no_seq INCREMENT BY 1 START WITH 200 Wykorzystanie sekwencji: INSERT INTO employee (emp_no, first_name, last_name, salary, dept_no, hire_date, job_code, job_grade, job_country) VALUES(emp_no_seq.NEXTVAL, ’Anna’, ’Kowalska’,5000, ’000’,sysdate,’Admin’,4,’USA’); Sekwencje Każde wywołanie metody NEXTVAL powoduje zwi˛ekszenie wartości sekwencji o zadany skok. Jeżeli wartość ta nie zostanie wykorzystana, np. z powodu bł˛edu w instrukcji INSERT, wycofania transakcji, zostaje utracona. Przy nast˛epnym wywołaniu NEXTVAL zwraca kolejna˛ wartość. Jedna˛ sekwencj˛e można wykorzystywać do generowania wartości kluczy głównych w kilku tabelach. Metoda CURRVAL nie zmienia wartości sekwencji, a jedynie zwraca bieżac ˛ a.˛ Uwaga. Metod˛e CURRVAL można stosować dopiero po pobraniu pierwszej wartości z sekwencji za pomoca˛ NEXTVAL. Wykorzystanie sekwencji w wyzwalaczach Wyzwalacz dla tabeli employee, wstawiajacy ˛ do pola klucza głównego emp_no kolejna˛ wartość pobrana˛ z sekwencji emp_no_seq. CREATE OR REPLACE TRIGGER wstaw_emp_no BEFORE INSERT ON employee FOR EACH ROW DECLARE numer INT; BEGIN IF (:NEW.emp_no IS NULL) THEN SELECT emp_no_seq.NEXTVAL INTO numer FROM dual; :NEW.emp_no := emp_no_seq.NEXTVAL; END IF; END;