Triggery w MySQL

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:

  1. CREATE
  2.     TRIGGER trigger_name trigger_time trigger_event
  3.     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.

  1. CREATE TABLE `test`.`bibl_logs` (
  2.   `id_log` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  3.   `l_bookt` VARCHAR(255),
  4.   `l_datetime` DATETIME NOT NULL,
  5.   PRIMARY KEY (`id_log`)
  6. )
+------------+------------------+------+-----+---------+----------------+
| 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.

  1. CREATE TRIGGER histlog BEFORE DELETE ON bibl_books
  2. FOR EACH ROW
  3. 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:

  1. BEGIN
  2.     DECLARE counter = INTEGER;
  3.     SELECT count(id_book) INTO counter FROM bibl_books;
  4.  
  5.     IF counter > 0 THEN
  6.         /* kod SQL */
  7.     END IF;
  8. 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

3 Responses to “Triggery w MySQL”


  1. Gravatar Icon 1 Gringom

    Świetny wpis. Dzięki i pozdrawiam :)

  2. Gravatar Icon 2 Jacek

    Tego mi brakowało - krótko i rzeczowo :)

  3. Gravatar Icon 3 Kris

    więcej danych opisanych w ten sam sposób :D:D:D super artykulik

Leave a Reply






O mnie

  • Programista PHP
  • Zwolennik Open Source
  • Użytkownik Linuksa (Debian)
  • Capoerista
  • Miłośnik Anime
  • Maniak optymalizacji i wydajności

Kategorie