Friday, October 19, 2018

Wyzwalacze


Wyzwalacze to specjalne funkcje które uruchamiane są w reakcji na jakieś zdarzenie na obiektach bazodanowych. Możesz stworzyć trigger który będzie np. zapisywał informacje o tym to i co zmienił w tabeli ludziki, albo zablokować jakiś rodzaj zmian.
Wyzwalacze mogą być uruchamiane przed lub po wydarzeniu które je wyzwala. Mogą działać na poziomie obiektu, albo na poziomie wiersza. W pierwszym przypadku wyzwalacz (trigger) uruchomi się tylko raz w związku ze zdarzeniem, niezależnie od ilości zmienianych wierszy. W drugim przypadku uruchomi się dla każdego zmienianego wiersza. Kiedy i jakie wyzwalacze stosować omówimy sobie nieco dalej. Na ten moment rozpoczniemy od najprostszego wyzwalacz.
Na wyzwalacz w PostgreSQL składają się dwie rzeczy. Wyzwalacz sam w sobie, oraz funkcja która przez ten wyzwalacz jest uruchamiana. To właśnie w tej funkcji opisywana jest cała mechanika jaka ma zostać wykonana. W samym wyzwalaczu opisane jest tylko kiedy owa funkcja ma zostać uruchomiona.

Wyzwalacze obiektowe




Nasz pierwszy wyzwalacz będzie wypisywał na konsolę komunikat za każdym razem gdy ktoś zmieni zawartość tabeli ludziki.
Zaczynamy od stworzenia funkcji która będzie zawierała całe "mięcho". Kod funkcji znajduje się poniżej:



create or replace function obserwator_funkcja() returns trigger as $$
begin
raise notice 'ktoś coś zmienił w ludzikach!';
end $$ language plpgsql;



Zwróć uwagę na typ zwracany przez tę funkcję - returns trigger - jeśli funkcja jest dedykowana pod wyzwalacz, musi mieć właśnie taką konstrukcję.

Po skompilowaniu funkcji musimy założyć wyzwalacz na tabelkę "ludziki":




create trigger obserwator_trigger
after update on ludziki
execute procedure obserwator_funkcja();




Wyzwalacz jako taki określa tylko moment uruchomienia funkcji. Przyjrzyj się linii 2 wyzwalacza. Funkcja zostanie uruchomiona po zdarzeniu update na tabelce ludziki. W ramach wyzwalacza uruchamiana jest nasza funkcja. Aby przetestować wyzwalacz dokonuję zmiany na wszystkich wierszach tabeli ludziki:




Jak widać choć aktualizacja dotyczyła kilku wieszy, wyzwalacz został uruchomiony tylko raz. Związane jest to z tym, że domyślnie wyzwalacz zakładany jest na poziomie obiektu a nie wiersza.



Wyzwalacze wierszowe




Jeśli chcemy by wyzwalacz uruchamiał się dla każdego zmienianego wiersza, musi to być wyzwalacz wierszowy. Poniżej znajduje się wierszowy wariant wyzwalacza z poprzedniego podrozdziału:



create trigger obserwator_trigger_wiersz
after update on ludziki
for each row
execute procedure obserwator_funkcja_wiersz();



Od poprzedniego odróżnia go klauzula "for each row". To za jej sprawą właśnie wyzwalacz będzie się uruchamiał dla każdego zmienianego wiersza. W związku ze zmianą wyzwalacza musimy zmienić też podpiętą funkcję:



create or replace function obserwator_funkcja_wiersz() returns trigger as $$
begin
raise notice 'ktoś coś zmienił w ludzikach!';
return new;
end $$ language plpgsql;



Różnica sprowadza się do klauzuli "return new". Co ona właściwie oznacza? Zwraca modyfikowany wiersz. Skąd on jednak tutaj się wziął i po co właściwie uruchamiać wyzwalacz dla każdego modyfikowanego wiersza? Wyzwalacze wierszowe stosuje się gdy zechcemy uzyskać dostęp do zmienianych wierszy, odczytać jego wartości przed zmianą i po. Możemy go również zmodyfikować w locie. Do nowej i starej postaci wiersza odnosimy się poprzez "new" i "old". Jeśli wyzwalacz jest założony nie "after" a "before" - czyli jest uruchamiany przed np. modyfikacją wiersza, to taki aktualizowany wiersz "przelatuje" przez nasz wyzwalacz, i możemy dokonać w locie jakichś zmian na nim. Na przykład uzupełnić jakieś kolumny. W związku z tym musimy w wyzwalaczu wierszowym oddać ten przelatujący wiersz.


Po modyfikacjach uruchamiam aktualizację danych po raz kolejny. Widzimy teraz że wyzwalacz uruchomił się dla wszystkich wierszy osobno.



Wykorzystajmy teraz predykaty "new" i "old". Do pól nowego i starego wiersza odnoszę się podając nazwę kolumny po new lub old:

create or replace function obserwator_funkcja_wiersz() returns trigger as $$
begin
raise notice 'Zmiana dla % %. old.wiek=% new.wiek=%', new.imie,new.nazwisko, old.wiek, new.wiek;
return new;
end $$ language plpgsql;


Sam wyzwalacz pozostaje bez zmian. Efekt działania:




Predefiniowane zmienne



Poza new i old PostgreSQL dostarcza również inne zmienne niosące ze sobą cenne informacje.

NEW
Nowa postać wiersza
OLD
Stara postać wiersza
TG_NAME
Nazwa wyzwalacza
TG_WHEN
Zwraca "BEFORE" lub "AFTER" w zależności od momentu uruchomienia wyzwalacza
TG_LEVEL
Zwraca "ROW" lub "STATEMENT" zależności czy jest to wyzwalacz na poziomie wiersza czy obiektu
TG_OP
Zwraca "INSERT" "UPDATE" "DELETE" "TRUNCATE" w zależności od instrukcji która uruchomiła wyzwalacz
TG_TABLE_NAME
Nazwa tabeli dla której wyzwalacz został wywołany




No comments:

Post a Comment

Bezpłatny kurs PL/pgSQL by Andrzej Klusiewicz

Cześć  :) Oddaję w Wasze ręce wersję 1.0.0.0.0.(0) swojego tutoriala dotyczącego języka PL/pgSQL - czyli proceduralnego języka przetwarza...