Momentami dochodzi do sytuacji, w których modyfikacja kodu aplikacji jest ostatecznością. Wtedy to rozwiązania pośrednie nie naruszające struktury systemu stają się niezwykle użyteczne.
Tak też było w tym przypadku, nie chciałem modyfikować istniejącego kodu PHP i zmian dokonałem na poziomie MySQL deklarując wyzwalacze (ang. triggers).
Definicja triggera w MySQL wygląda następująco:
- CREATE
- TRIGGER trigger_name trigger_time trigger_event
- ON tbl_name FOR EACH ROW trigger_stmt
Trigger_event to zdarzenie, po którym następuje wywołanie określonego bloku instrukcji. Możliwe opcje to:
- INSERT - dodanie rekordu do tabeli
- UPDATE - uaktualnienie rekordu
- DELETE - usunięcie rekordu
Z czego triggery mogą być wywoływane przed danym zdarzeniem - BEFORE lub po wystąpieniu danego zdarzenia - AFTER.
Rozważmy następujący scenariusz:
Istnieje tabela przechowująca dane dotyczące książek, jest to system wykorzystywany w bibliotece XYZ. Dostęp do systemu ma wielu użytkowników za pośrednictwem panelu administracyjnego. Możliwe jest dodawanie, usuwanie oraz modyfikacja pozycji książkowych. Aplikacja tworzona była dość dawno i z tego też względu zapomniano o zaimplementowaniu potrzebnych dzisiaj funkcjonalności.
Pewnego dnia bibliotekarka chcąc dodać nową książkę do bazy danych, zauważyła iż ktoś z użytkowników popełnił błąd podczas edycji ostatnio dodanych pozycji i usunął jedną z książek. Chcąc powiadomić użytkownika o błędzie uświadomiła sobie, że nie jest w stanie się dowiedzieć, który z kilkunastu bywalców biblioteki dokonał błędnej modyfikacji, kiedy oraz jaka książka została usunięta. Wezwano więc informatyka aby zaimplementował mechanizm pozwalający na śledzenie historii zmian dokonywanych przez osoby z poziomu panelu administracyjnego.
System był przestarzały, tym samym w kodzie źródłowym istniały rozwiązania już nie tak popularne jak niegdyś. Programista stwierdził, iż szybciej będzie jeżeli skorzysta z udogodnień oferowanych przez MySQL w postaci triggerów, niżeli miałby tracić czas na analizę kodu źródłowego i jego modyfikację.
Struktura tabeli zawierającej pozycje książkowe przedstawia się następująco:
+---------------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------------+------------------+------+-----+---------+----------------+ | id_book | int(10) unsigned | NO | PRI | NULL | auto_increment | | b_title | varchar(45) | NO | | NULL | | | b_description | varchar(255) | NO | | NULL | | | b_datetime | datetime | YES | | NULL | | +---------------+------------------+------+-----+---------+----------------+
Aby możliwe, było prowadzenie historii zmian potrzebna jest dodatkowa tabela, do której będą zapisywane logi.
- CREATE TABLE `test`.`bibl_logs` (
- `id_log` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
- `l_bookt` VARCHAR(255),
- `l_datetime` DATETIME NOT NULL,
- PRIMARY KEY (`id_log`)
- )
+------------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+------------------+------+-----+---------+----------------+ | id_log | int(10) unsigned | NO | PRI | NULL | auto_increment | | l_bookt | varchar(255) | YES | | NULL | | | l_datetime | datetime | YES | | NULL | | +------------+------------------+------+-----+---------+----------------+
Teraz można przejść do deklaracji wyzwalacza dla tabeli bibl_books. Podczas usuwania rekordu z tabeli zawierającej książki automatycznie dodawany będzie wpis w tabeli z logami - historia zmian.
- CREATE TRIGGER histlog BEFORE DELETE ON bibl_books
- FOR EACH ROW
- INSERT INTO bibl_logs (id_log, l_bookt, l_datetime) VALUES ('', OLD.b_title, NOW());
W ten sposób wpisy usuwane z tabeli bibl_books będą lądować w tabeli bibl_logs.
Wyzwalacze w wielu sytuacjach mogą stać się bardzo przydatne, momentami zaoszczędzają nam konieczności ingerencji w kod źródłowy aplikacji aby uzyskać pożądane efekty. Możliwa jest także deklaracja zmiennych oraz przypisywanie do nich wartości w trigerrach:
- BEGIN
- DECLARE counter = INTEGER;
- SELECT count(id_book) INTO counter FROM bibl_books;
- IF counter > 0 THEN
- /* kod SQL */
- END IF;
- END;
Więcej informacji na temat trigerrów można znaleźć na poniższych stronach:
http://www.quest-pipelines.com/newsletter-v8/0207_D.htm
http://forge.mysql.com/wiki/Triggers
karpowicz.net
gmail.com
Świetny wpis. Dzięki i pozdrawiam
Tego mi brakowało - krótko i rzeczowo
więcej danych opisanych w ten sam sposób :D:D:D super artykulik