Wyzwalacze Bazy danych 201
202 Bazy danych Przegląd zagadnień Czym sa wyzwalacze i kiedy je stosujemy Rodzaje wyzwalaczy Podsumowanie Laboratorium Wyzwalacz (ang. trigger) jest specjalnym rodzajem procedury składowanej. W przeciwieństwie do zwykłej procedury składowanej wyzwalacz nie moŝe zostać jawnie wywołany. Wyzwalacz jest wywoływany w reakcji na określone akcje. Akcje te to wykonanie przez uŝytkownika określonego polecenia SQL (INSERT, UPDATE, DELETE) na danej tabeli, dla której został określony wyzwalacz.
Bazy danych 203 Czym są wyzwalacze i kiedy je stosujemy Tworzenie wyzwalaczy Zastosowania wyzwalaczy Transakcyjnosc wyzwalaczy
204 Bazy danych Tworzenie wyzwalaczy Wyzwalacze tworzymy uŝywając polecenia CREATE TRIGGER. W definicji wyzwalacza określamy: nazwę wyzwalacza; dla jakiej tabeli tworzymy wyzwalacz; na jakie akcje wyzwalacz będzie reagował; jakiego typu wyzwalacz tworzymy; ciało wyzwalacza (odpowiednik ciała procedury składowanej) - czyli kod wykonywany przez wyzwalacz. PoniŜej podano przykład utworzenia prostego wyzwalacza (o nazwie t_informacja), który jest wywoływany po wykonaniu przez uŝytkownika polecenia INSERT na tabeli o nazwie tabela1(tu konkretny przykład wysyłania e-maila do administratora z informacją o wstawieniu nowych danych do tabeli). Rys. 10.1 Przykład stworzenia wyzwalacza typu AFTER Zastosowania wyzwalaczy Wyzwalacze znajdują wiele zastosowań w bazach danych. Przede wszystkim stosujemy wyzwalacze wszędzie tam, gdzie w inny sposób nie da się weryfikować integralności danych, a zwłaszcza ich zgodności z regułami logiki biznesowej. Na przykład, chcemy, by w pewnej kolumnie tabeli wstawiane były tylko wartości unikalne, ale jednocześnie zezwalamy na wstawienie wartości NULL. Jedynym rozwiązaniem jest uŝycie wyzwalacza, który sprawdzi, czy wstawiana właśnie wartość juŝ w danym polu wystąpiła, a jeŝeli uŝytkownik wstawia wartość NULL, to wyzwalacz mu na to pozwoli (tego efektu nie moŝna osiągnąć innymi metodami - np. uŝywając indeksów, ustawiając właściwość unikalności kolumny lub uŝywając kryteriów sprawdzających dane wstawiane w kolumnę). Drugie zastosowanie to wszelkiego typu automatyzacja zadań administracyjnych w bazie danych (wszelkiego rodzaju "przypominacze", obsługa nietypowych działań czy chociaŝby wysyłanie wiadomości przez e- mail lub pager). Wreszcie z uwagi na pewne cechy wyzwalacze pozwalają na określony typ przetwarzania transakcyjnego. Transakcyjność wyzwalaczy Instrukcje wykonywane w ciele wyzwalacza są traktowane jako fragment transakcji jawnie lub niejawnie rozpoczętej przez uŝytkownika. Oznacza to, Ŝe za pomocą wyzwalacza moŝna zatwierdzić (COMMIT TRAN) lub
Bazy danych 205 odrzucić (ROLLBACK TRAN) zmiany w tabeli wprowadzone przez uŝytkownika. MS SQL Server wprowadza dwie tabele (o nazwach inserted oraz deleted) przechowujące zmienione lub usunięte przez uŝytkownika wartości. Z tabel tych mogą korzystać wyzwalacze. Dzięki temu moŝna za pomocą wyzwalaczy cofnąć wykonanie przez uŝytkownika zmiany w tabeli. Więcej o działaniu wyzwalaczy dowiesz się w części ćwiczeniowej.
206 Bazy danych Rodzaje wyzwalaczy Wyzwalacze typu po Wyzwalacze typu zamiast Wyzwalacze wykonywane są automatycznie przez serwer w odpowiedzi na akcję uŝytkownika (wykonanie jednego z poleceń języka SQL modyfikujących dane w tabeli). WyróŜniamy dwa rodzaje wyzwalaczy: - wyzwalacze typu "po" (ang. AFTER), - wyzwalacze tpyu "zamiast" (ang. INSTEAD OF).
Bazy danych 207 Wyzwalacze typu "po" Jak sama nazwa wyzwalaczy sugeruje, są one wykonywane po wykonaniu określonego polecenia. W definicji wyzwalacza typu "po" przy liście poleceń język SQL, na które wyzwalacz ma reagować, pojawia się słowo kluczowe AFTER. Z uwagi na to, Ŝe wyzwalacze typu "po" nie ingerują w wykonanie polecenia języka SQL, moŝemy dla jednej tabeli i jednego polecenia SQL (np. dla INSERT) zdefiniować więcej niŝ jeden wyzwalacz tego typu. Kolejność wykonywania wyzwalaczy ustala się przy pomocy odpowiedniej systemowej procedury składowanej (w MS SQL Server jest to procedura sp_settriggerorder). Wyzwalacze typu "zamiast" Dla kaŝdej akcji (dla kaŝdego polecenia modyfikującego dane) w tabeli moŝemy zdefiniować jeden wyzwalacz typu "zamiast". Wyzwalacze tego typu są wykonywane, jak wskazuje nazwa, zamiast określonego polecenia SQL. W definicji wyzwalaczy tego typu przy liście poleceń język SQL, na które wyzwalacz ma reagować, pojawia się słowo kluczowe INSTEAD OF.
208 Bazy danych Podsumowanie Czym sa wyzwalacze i kiedy je stosujemy Rodzaje wyzwalaczy Wyzwalacze są szczególnym rodzajem procedur składowanych. W przeciwieństwie do zwykłych procedur są wykonywane automatycznie jako reakcja na wykonanie określonych poleceń SQL i nie mogą być wywołane jawnie przez uŝytkownika.
Laboratorium Bazy danych 209
210 Bazy danych Planowanie i tworzenie wyzwalaczy Wyzwalacze (ang. triggers) są szczególnymi procedurami składowanymi. Nie moŝna ich wywołać bezpośrednio z poziomu kodu T-SQL. Wyzwalacze działają w odpowiedzi na wykonywanie operacji INSERT, UPDATE lub DELETE. W tej lekcji poznasz bliŝej działanie wyzwalaczy, ich typy oraz przeznaczenie. Krok 1 - Kiedy stosować wyzwalacze? Wyzwalacze stosujemy w celu zapewnienia spójności logicznej danych w bazie. Pamiętaj jednak, Ŝe jeśli spójność tą moŝna osiągnąć innymi środkami (nakładając ograniczenia lub uŝywając odpowiednich typów danych dla kolumn), to wyzwalacze są ostatnią opcją i raczej się unika ich stosowania bez potrzeby (ze względu na wydajność). Przykładowe sytuacje, kiedy moŝesz uŝyć wyzwalacza: jeśli nie wystarcza Ci funkcjonalność deklarowanych metod wymuszania spójności danych (np. ograniczeń w tabelach), jeśli zmiany w jednej tabeli muszą dotknąć kolumn w powiązanych tabelach (np. dodanie zakupu powoduje zmniejszenie w innej tabeli ilości towaru na stanie), ale nie licząc pól będących kluczami obcymi (tu moŝna wymusić kaskadowe zmiany bez uŝycia wyzwalaczy), jeśli baza jest zdenormalizowana (czasem się tak zdarza, np. ze względu na współpracę baz danych z hurtowniami danych) i naleŝy przetworzyć dane w celu usunięcia nadmiarowości, jeśli wartość w jednej tabeli nie moŝe być równa wartości w innej tabeli, jeśli chcesz, by serwer zwracał Twoje komunikaty, w innych sytuacjach, w których przy wykonywaniu poleceń DML (bez SELECT) chcesz wykonać jakąś nietypową operację na danych dotkniętych operacją zmiany. Masz do dyspozycji dwa tpy wyzwalaczy: wyzwalacze typu ZAMIAST (ang. instead of) oraz wyzwalacze typu PO (ang. after). Zobaczmy w działaniu oba typy. Krok 2 - Zobacz w działaniu wyzwalacz typu ZAMIAST Zaloguj się do maszyny wirtualnej ZBD jako uŝytkownik Administrator z hasłem P@ssw0rd. Kliknij Start. Z grupy programów Microsoft SQL Server 2005 uruchom SQL Server Management Studio. W oknie logowania kliknij Connect. Kliknij w menu głównym programu Management Studio na File. Kliknij Open - File. Odszukaj plik C:\Labs\Lab10\instead_demo.sql i kliknij Open. Zaznacz i uruchom (klawisz F5) fragment kodu oznaczony w komentarzu jako (1).
Bazy danych 211 -- (1) przygotujmy tabele -- do testowania wyzwalaczy USE Northwind SELECT EmployeeID, LastName, FirstName, BirthDate, ReportsTo INTO Employees_kopia FROM Employees Wynikiem wykonania powyŝszego kodu jest utworzenie w bazie danych Northwind tabeli Employees_kopia, w której znajdą się wybrane kolumny skopiowane z tabeli Employees. Tabela ta będzie nam potrzebna do testowania wyzwalaczy. MoŜliwe, Ŝe we wcześniejszych lekcjach juŝ tabela o takiej nazwie w bazie istnieje. Usuń ją wówczas z bazy i wykonaj powyŝszy kod w celu utworzenia tabeli na nowo. Zaznacz i uruchom (F5) fragment kodu oznaczony w komentarzu jako (2), by zobaczyć, jakie dane zawiera tabela. Zwróć uwagę na kolumnę ReportsTo - policz, ile razy występuje w niej identyfikator równy 2 (powinieneś naliczyć 5 takich wierszy). -- (2) zobaczmy, co znajduje sie w tabeli SELECT * FROM Employees_kopia EmployeeID LastName FirstName BirthDate ReportsTo ----------- -------------------- ---------- ----------------------- ----------- 1 Davolio Nancy 1948-12-08 00:00:00.000 2 2 Fuller Andrew 1952-02-19 00:00:00.000 NULL 3 Leverling Janet 1963-08-30 00:00:00.000 2 4 Peacock Margaret 1937-09-19 00:00:00.000 2 5 Buchanan Steven 1955-03-04 00:00:00.000 2 6 Suyama Michael 1963-07-02 00:00:00.000 5 7 King Robert 1960-05-29 00:00:00.000 5 8 Callahan Laura 1958-01-09 00:00:00.000 2 9 Dodsworth Anne 1966-01-27 00:00:00.000 5
212 Bazy danych Zaznacz i uruchom (F5) fragment kodu oznaczony w komentarzu jako (3). -- (3) utworzmy wyzwalacz typu ZAMIAST CREATE TRIGGER instead_insert_employee ON Employees_kopia INSTEAD OF INSERT AS IF (SELECT Count(*) FROM Employees, inserted WHERE Employees.ReportsTo = inserted.reportsto AND Employees.ReportsTo IS NOT NULL) < 5 BEGIN INSERT INTO Employees_kopia SELECT LastName, FirstName, BirthDate, ReportsTo FROM inserted END ELSE BEGIN PRINT 'Pracownik nie moze miec wiecej niz 5 podwladnych.' END Wynikiem wykonania powyŝszego kodu jest utworzenie w tabeli Employees_kopia wyzwalacza typu ZAMIAST o nazwie instead_insert_employee dla polecenia INSERT. PowyŜszy wyzwalacz słuŝy do zaimplementowania warunku, który mówi, Ŝe kaŝdy pracownik moŝe mieć maksymalnie pięciu bezpośrednio podlegających podwładnych (o tym, kto jest szefem, mówi kolumna ReportsTo zawierająca identyfikator szefa). Tego warunku inaczej niŝ przy pomocy wyzwalacza osiągnąć nie moŝna. Zwróć uwagę na wykorzystanie tabeli inserted, która zawiera dane, które uŝytkownik usiłuje w danym momencie wstawić do tabeli (przy automatycznym wywołaniu wyzwalacza typu ZAMIAST dane nie zostają wstawione do tabeli Employees_kopia, tylko właśnie do tabeli inserted, z której następnie moŝna skorzystać). Jak juŝ zapewne wiesz z wykładów, SQL Server oferuje na potrzeby wyzwalaczy dwie tabele tymczasowe - inserted oraz deleted. Pierwsza z nich przechowuje dane, które miały zostać wstawione do tabeli, ale uruchomienie wyzwalacza uprzedziło operację wstawienia. Druga tabela słuŝy do przechowywania danych usuwanych z tabeli oraz danych modyfikowanych (tabela przechowuje dane sprzed modyfikacji). Polecenie CREATE TRIGGER musi zawsze być pierwszym poleceniem we wsadzie. Pozostałe polecenia w tym samym wsadzie traktowane są jako ciało definicji wyzwalacza.
Bazy danych 213 Zaznacz i uruchom (F5) fragment kodu oznaczony w komentarzu jako (4). -- (4) wyprobujmy dzialanie wyzwalacza INSERT INTO Employees_kopia(LastName, FirstName, BirthDate, ReportsTo) VALUES ('Kowalski','Jan','1970/04/10',2) PowyŜszy kod jest próbą wstawienia do tabeli Employees_kopia nowego pracownika, którego szefem jest pracownik o identyfikatorze równym 2 (patrz kolumna ReportsTo). Próba kończy się wyświetleniem informacji: Pracownik nie moze miec wiecej niz 5 podwladnych w zakładce Messages. Zaznacz i uruchom (F5) ponownie fragment kodu oznaczony w komentarzu jako (2). ZauwaŜ, Ŝe nie został dodany Ŝaden nowy wiersz do tabeli. Zmień wartość wstawianą w kolumnę ReportsTo z 2 na 5. Zaznacz i uruchom (F5) ten fragment kodu. Tym razem operacja przebiegła pomyślnie. Zaznacz i uruchom (F5) ponownie fragment kodu oznaczony w komentarzu jako (2). ZauwaŜ, Ŝe został dodany nowy wiersz do tabeli. Krok 3 - Zobacz w działaniu wyzwalacz typu PO Kliknij w menu głównym programu Management Studio na File. Kliknij Open - File. Odszukaj plik C:\Labs\Lab10\after_demo.sql i kliknij Open. Zaznacz i uruchom (klawisz F5) fragment kodu oznaczony w komentarzu jako (1). -- (1) przygotujmy dodatkowa tabele -- do testowania wyzwalaczy USE Northwind CREATE TABLE Employees_deleted ( EmployeeID int, LastName nvarchar(40), FirstName nvarchar(20), BirthDate datetime, ReportsTo int, WhenDeleted datetime ) Wynikiem wykonania powyŝszego kodu jest utworzenie w bazie danych Northwind nowej tabeli Employees_deleted, w której będziemy chcieli przechowywać dane usuwane z tabeli Employees_kopia (dodatkowo dodaliśmy kolumnę WhenDeleted, która będzie przechowywała datę i czas usunięcia wiersza z tabeli Employees_kopia).
214 Bazy danych Zaznacz i uruchom (F5) fragment kodu oznaczony w komentarzu jako (2). -- (2) utworzmy dwa wyzwalacze typu PO CREATE TRIGGER after_delete_employee1 ON Employees_kopia AFTER DELETE AS INSERT INTO Employees_deleted SELECT *, GetDate() FROM deleted CREATE TRIGGER after_delete_employee2 ON Employees_kopia AFTER DELETE AS PRINT 'Wykonano usuwanie.' Wynikiem wykonania powyŝszego kodu jest utworzenie w tabeli Emoloyees_kopia dwóch wyzwalaczy typu PO: after_delete_employee1 oraz after_delete_employee2. Pierwszy wyzwalacz ma za zadanie skopiować usuwane z tabeli Employees_kopia dane do tabeli Employees_deleted. Wykorzystuje przy tym tymczasową tabelę deleted. Drugi wyzwalacz jest prostszy i jedynym jego zadaniem jest poinformowanie o wykonaniu polecenia DELETE (niewaŝne, czy polecenie usunęło jakieś wiersze z tabeli). Zaznacz i uruchom (F5) fragment kodu oznaczony w komentarzu jako (3). -- (3) przetestujmy dzialanie wyzwalaczy DELETE FROM Employees_kopia WHERE LastName = 'Davolio' Wynikiem wykonania powyŝszego kodu jest usunięcie z tabeli Employees_kopia pracownika o nazwisku Davolio. W zakładce Messages pojawiają się dwa komunikaty. Pierwszy komunikat dotyczy wyzwalacza after_delete_employee1 (jeden usunięty wiersz), zaś drugi wyzwalacza after_delete_employee2 (informacja o wykonaniu polecenia usuwania). Zaznacz i uruchom (F5) fragment kodu oznaczony w komentarzu jako (3). -- (4) zobaczmy zawartosc tabeli -- zawierajacej usuniete rekordy SELECT * FROM Employees_deleted
Bazy danych 215 W wyniku wykonania powyŝszego kodu wyświetlana jest zawartość tabeli Employees_deleted, która w tej chwili powinna zawierać wiersz właśnie usunięty z tabeli Employees_kopia, na przykład: EmployeeID LastName FirstName BirthDate ReportsTo WhenDeleted ----------- ---------- ----------- ----------------------- ----------- ----------------------- 1 Davolio Nancy 1948-12-08 00:00:00.000 2 2004-05-10 13:28:38.933 Krok 4 - Zmień kolejność wykonywania wyzwalaczy typu PO Zaznacz i uruchom (F5) fragment kodu oznaczony w komentarzu jako (3). -- (5) zmienmy kolejnosc wykonywania wyzwalaczy EXEC sp_settriggerorder @triggername = 'after_delete_employee2', @order = 'first', @stmttype = 'DELETE' Wynikiem wykonania powyŝszego kodu jest ustawienie wyzwalacza after_delete_employee2 na początku (ang. first - pierwszy) kolejki wykonywania wyzwalaczy typu PO dla operacji DELETE w tabeli Employees_kopia. Jeśli nie ustalisz kolejności wykonywania wyzwalaczy typu PO w tabeli, to będą one wykonywane w przypadkowej kolejności. Do ustalenia kolejności moŝesz uŝyć procedury systemowej sp_settiggerorder. Procedura ta ma trzy parametry: nazwę wyzwalacza, parametr określający połoŝenie wyzwalacza w kolejce (moŝliwe opcje: first - pierwszy w kolejce, last - ostatni w kolejce, none - połoŝenie nieokreślone) oraz nazwę polecenia dla którego porządkujemy kolejność wykonywania wyzwalaczy. Zaznacz i uruchom (F5) ponownie fragment kodu oznaczony w komentarzu jako (4) (polecenie DELETE). Zajrzyj do zakładki Messages i sprawdź, czy najpierw wyświetlony został komunikat wyzwalacza after_delete_employee2.