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;