Generator wyzwalacza SQL
Kod CREATE TRIGGER dla MySQL / MariaDB i PostgreSQL z kontrolą NEW, OLD oraz momentu BEFORE i AFTER
-
1Wprowadź dane
Wpisz treść, wklej tekst lub załaduj plik z dysku. -
2Kliknij przycisk
Narzędzie natychmiast przetworzy Twoje dane w przeglądarce. -
3Pobierz wynik
Skopiuj gotowy tekst lub zapisz plik na urządzeniu.
return "Wynik gotowy w 0.1s";
}
Bez BEGIN i END, generator doda je sam. Do kolumn odwołujesz się przez NEW.kolumna i OLD.kolumna.
Wyzwalacz update_timestamp
Uruchamia się przed zmianą każdego wiersza w tabeli users. Nie wykryto typowych błędów.
Baza
Linii kodu
Linii treści
Dostępne rekordy
Uwagi
Kod SQL · MySQL / MariaDB
Ściąga: wyzwalacze w MySQL i PostgreSQL
| Czynność | MySQL / MariaDB | PostgreSQL |
|---|---|---|
| Lista wyzwalaczy tabeli | SHOW TRIGGERS LIKE 'users'; | SELECT tgname FROM pg_trigger WHERE tgrelid = 'users'::regclass AND NOT tgisinternal; |
| Podgląd definicji | SHOW CREATE TRIGGER `update_timestamp`; | SELECT pg_get_triggerdef(oid) FROM pg_trigger WHERE tgname = 'update_timestamp'; |
| Usunięcie | DROP TRIGGER IF EXISTS `update_timestamp`; | DROP TRIGGER IF EXISTS update_timestamp ON users; |
| Chwilowe wyłączenie | brak polecenia: usuń i utwórz ponownie | ALTER TABLE users DISABLE TRIGGER update_timestamp; |
| Wspólne dla obu | SELECT trigger_name, action_timing, event_manipulation FROM information_schema.triggers WHERE event_object_table = 'users'; | to samo zapytanie działa w PostgreSQL |
| Zdarzenie | NEW (nowy wiersz) | OLD (stary wiersz) | Typowe użycie |
|---|---|---|---|
| INSERT | tak; w BEFORE można zmieniać | brak | wartości domyślne, walidacja, liczniki |
| UPDATE | tak; w BEFORE można zmieniać | tak, tylko odczyt | znacznik updated_at, historia zmian |
| DELETE | brak | tak, tylko odczyt | audyt, archiwum usuniętych wierszy |
BEFORE czy AFTER?
BEFORE działa przed zapisem: poprawisz dane (SET NEW.kolumna = … w MySQL, NEW.kolumna := … w PostgreSQL) albo przerwiesz operację błędem (SIGNAL / RAISE EXCEPTION). AFTER widzi zapisany wiersz, więc nadaje się do audytu, logów i zmian w innych tabelach. Zmiana NEW w AFTER nic nie daje, a MySQL zgłasza wtedy błąd.
MySQL i MariaDB
Treść między BEGIN i END zawiera średniki, dlatego w konsoli mysql zmienia się separator poleceń (DELIMITER $$). Z aplikacji (PDO, DB::unprepared() w Laravelu) wysyłasz kod bez DELIMITER. Wyzwalacz nie może zmieniać tabeli, na której działa, a MySQL zawsze uruchamia go dla każdego wiersza.
PostgreSQL
Wyzwalacz wywołuje funkcję zwracającą typ trigger, dlatego powstają dwie instrukcje: CREATE FUNCTION i CREATE TRIGGER. Wyzwalacz BEFORE dla wiersza musi zwrócić NEW (przy DELETE: OLD); zwrócenie NULL pomija operację na tym wierszu. EXECUTE FUNCTION działa od wersji 11, w starszych pisze się EXECUTE PROCEDURE.
Typowe pułapki
Wyzwalacz działa przy każdym wierszu, także przy masowym imporcie, więc ciężka logika spowalnia zapis. TRUNCATE nie uruchamia wyzwalaczy DELETE. Wyzwalacz zmieniający inną tabelę uruchamia jej wyzwalacze, co grozi kaskadą. Logiki w bazie nie widać w kodzie aplikacji, więc trzymaj ją w migracjach.
Oceń to narzędzie:
Powiązane narzędzia
Inne narzędzia, które mogą Ci się przydaćWyzwalacz SQL (trigger): co to jest
Wyzwalacz SQL (trigger) to kod, który baza danych uruchamia automatycznie przy INSERT, UPDATE lub DELETE na wskazanej tabeli. Utrzymuje znaczniki czasu, prowadzi audyt, pilnuje poprawności danych albo aktualizuje powiązane tabele. Generator składa gotowe polecenie CREATE TRIGGER dla MySQL / MariaDB oraz PostgreSQL.
Rodzaje wyzwalaczy
| Moment | Zdarzenie | Zastosowanie |
|---|---|---|
| BEFORE | INSERT/UPDATE | walidacja, ustawienie lub poprawienie wartości kolumn przez NEW |
| BEFORE | DELETE | zablokowanie usunięcia błędem (SIGNAL / RAISE EXCEPTION) |
| AFTER | INSERT/UPDATE/DELETE | audyt, aktualizacja innych tabel |
W wyzwalaczu INSERT dostępny jest tylko rekord NEW, w DELETE tylko OLD, a w UPDATE oba. Wartości NEW można zmieniać wyłącznie w BEFORE; OLD służy tylko do odczytu.
Dobre praktyki
- nie umieszczaj ciężkiej logiki w triggerach — trudno je debugować,
- uważaj na rekurencję: w PostgreSQL trigger zmieniający własną tabelę uruchomi się ponownie, a MySQL takiej zmiany w ogóle nie wykona,
- dokumentuj każdy wyzwalacz i jego skutki, najlepiej w migracjach razem ze schematem,
- w PostgreSQL wyzwalacz zawsze wywołuje funkcję (
CREATE TRIGGER ... EXECUTE FUNCTION); generator tworzy ją razem z wyzwalaczem.
Jak działa generator wyzwalacza SQL
Podajesz bazę danych (MySQL / MariaDB albo PostgreSQL), nazwę wyzwalacza, tabelę, moment (BEFORE lub AFTER), zdarzenie (INSERT, UPDATE, DELETE) oraz treść, czyli instrukcje SQL do wykonania. Na tej podstawie generator buduje kod CREATE TRIGGER w składni wybranej bazy. Narzędzie nie łączy się z żadną bazą: składa tekst polecenia, który kopiujesz albo pobierasz jako plik .sql i uruchamiasz w swoim kliencie SQL lub migracji.
Treść wpisujesz bez BEGIN i END, bo generator dodaje je sam; brakujący średnik na końcu ostatniej linii też jest uzupełniany. Dla MySQL nazwy trafiają w odwrotne apostrofy, a kod dostaje klauzulę FOR EACH ROW, blok BEGIN … END i opcjonalnie polecenia DELIMITER. Dla PostgreSQL powstają dwie instrukcje: funkcja fn_nazwa() zwracająca typ trigger w języku plpgsql oraz CREATE TRIGGER z EXECUTE FUNCTION. Jeśli treść nie zawiera RETURN, generator dopisuje właściwy zwrot: RETURN NEW dla BEFORE INSERT/UPDATE, RETURN OLD dla BEFORE DELETE i RETURN NULL dla AFTER oraz wyzwalaczy FOR EACH STATEMENT.
Po wygenerowaniu narzędzie analizuje treść i ostrzega przed typowymi błędami: odwołaniem do OLD w INSERT lub do NEW w DELETE, zmianą NEW w AFTER, próbą zmiany OLD, modyfikacją tabeli, na której działa wyzwalacz, zbędnym BEGIN/END w polu treści i liniami bez średnika. Do wyboru są cztery gotowe przykłady: znacznik czasu, audyt usunięć, stany magazynowe i walidacja ceny, każdy w wersji dla obu baz.
Przykład krok po kroku
- Wybierz bazę danych MySQL / MariaDB.
- Podaj nazwę tabeli:
users. - Ustaw moment BEFORE i zdarzenie UPDATE.
- Wpisz nazwę wyzwalacza:
update_timestamp. - W polu treści wpisz:
SET NEW.updated_at = NOW(); - Zostaw zaznaczoną opcję DELIMITER i kliknij „Generuj SQL”.
Wynik ma 10 linii i nadaje się do wklejenia w konsoli mysql:
DELIMITER $$
CREATE TRIGGER `update_timestamp`
BEFORE UPDATE ON `users`
FOR EACH ROW
BEGIN
SET NEW.updated_at = NOW();
END$$
DELIMITER ;
Po przełączeniu na PostgreSQL treść przykładu zmienia się na NEW.updated_at := NOW();, a kod ma 14 linii:
CREATE OR REPLACE FUNCTION fn_update_timestamp()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
NEW.updated_at := NOW();
RETURN NEW;
END;
$$;
CREATE TRIGGER update_timestamp
BEFORE UPDATE ON users
FOR EACH ROW
EXECUTE FUNCTION fn_update_timestamp();
Gdy kod MySQL trafia do aplikacji (PDO, DB::unprepared() w Laravelu), odznacz DELIMITER: to polecenie klienta mysql, a nie serwera, więc wysłane przez sterownik kończy się błędem składni.
Parametry generatora i ich wpływ na wynik
| Parametr | Możliwe wartości | Efekt w kodzie |
|---|---|---|
| Baza danych | MySQL / MariaDB, PostgreSQL | MySQL: BEGIN … END w samym wyzwalaczu; PostgreSQL: osobna funkcja plpgsql i EXECUTE FUNCTION |
| Moment | BEFORE, AFTER | Ustawia słowo kluczowe przed zdarzeniem; w PostgreSQL decyduje też o dopisanym RETURN |
| Zdarzenie | INSERT, UPDATE, DELETE | Określa, na jaką operację reaguje trigger (jedno zdarzenie na wyzwalacz) |
| Tabela | identyfikator, opcjonalnie baza.tabela lub schemat.tabela | Wstawiana po ON; w MySQL przy zapisie z kropką nazwa wyzwalacza też dostaje prefiks bazy |
| Nazwa wyzwalacza | litery łacińskie, cyfry i _, do 64 znaków (MySQL) lub 63 (PostgreSQL) | Wstawiana po CREATE TRIGGER; w PostgreSQL również w nazwie funkcji fn_… |
| Treść | instrukcje SQL, do 5000 znaków | Wstawiana w blok BEGIN … END z wcięciem 4 spacji |
| DROP TRIGGER IF EXISTS | opcja | Usuwa wyzwalacz o tej nazwie przed utworzeniem nowego |
| DELIMITER | opcja, tylko MySQL | Otacza kod poleceniami DELIMITER $$ … DELIMITER ; (gdy treść zawiera $$, separatorem jest //) |
| IF NOT EXISTS | opcja, MySQL 8.0.29+ i MariaDB 10.1.4+ | Pomija tworzenie, jeśli wyzwalacz już istnieje |
| FOR EACH ROW | opcja, tylko PostgreSQL | Bez zaznaczenia powstaje FOR EACH STATEMENT (raz na polecenie, bez NEW i OLD); w MySQL zawsze FOR EACH ROW |
Praktyczne wskazówki
- Testuj na kopii bazy: wygenerowany trigger uruchom najpierw w środowisku testowym.
- Nazywaj opisowo. Nazwa wyzwalacza powinna odzwierciedlać tabelę i operację, np. users_before_update_timestamp, co ułatwia późniejsze zarządzanie.
- MySQL od wersji 5.7.2 pozwala na kilka triggerów BEFORE UPDATE na jednej tabeli; kolejność ustala się klauzulą FOLLOWS lub PRECEDES, której generator nie dodaje. PostgreSQL uruchamia takie wyzwalacze w kolejności alfabetycznej nazw.
- W PostgreSQL ponowne uruchomienie kodu podmieni funkcję (CREATE OR REPLACE FUNCTION), ale CREATE TRIGGER zgłosi błąd, gdy wyzwalacz już istnieje. Zaznacz wtedy opcję DROP TRIGGER IF EXISTS.
Ograniczenia narzędzia
- Brak pełnej walidacji składni: generator sprawdza nazwy i ostrzega przed typowymi błędami, ale nie parsuje treści, więc literówka w SQL wyjdzie dopiero w bazie.
- Nie obsługuje zaawansowanych klauzul, takich jak WHEN, REFERENCING czy FOLLOWS, ani wyzwalaczy INSTEAD OF i TRUNCATE; generuje podstawową postać.
- Nie zarządza uprawnieniami: nie dodaje klauzuli DEFINER ani nie sprawdza, czy użytkownik ma prawo utworzyć trigger (w MySQL potrzebne jest uprawnienie TRIGGER do tabeli).
- Nie zna stanu Twojej bazy, więc nie wykryje, że wyzwalacz o tej nazwie już istnieje. Przed konfliktem chronią opcje DROP TRIGGER IF EXISTS i IF NOT EXISTS.
Kiedy generator wyzwalacza SQL okazuje się przydatny
- Migracja logiki z aplikacji do bazy: gdy przenosisz reguły biznesowe z kodu do warstwy danych, szybko tworzysz szkielety triggerów dla wielu tabel.
- Nauka różnic między bazami. Przełączając MySQL i PostgreSQL na tym samym przykładzie, widzisz, czym różni się przypisanie do NEW (
SET NEW.x = …kontraNEW.x := …), zgłaszanie błędu (SIGNAL kontra RAISE EXCEPTION) i dlaczego PostgreSQL wymaga funkcji. - Prototypowanie i testy integracyjne: w kontenerze bazy potrzebujesz triggera, który rejestruje zmiany. Przykład „Audyt usunięć” zapisuje id usuniętego wiersza do tabeli audit_log, którą trzeba wcześniej utworzyć.
Najczęstsze błędy przy generowaniu i wdrażaniu triggerów
Jednym z najczęstszych problemów jest pominięcie zmiany separatora w konsoli mysql. Bez polecenia DELIMITER klient potraktuje średnik wewnątrz bloku BEGIN...END jako koniec instrukcji i przerwie wykonywanie; generator dodaje DELIMITER $$, a na końcu przywraca domyślny separator. Odwrotny błąd to wysyłanie DELIMITER przez PDO lub inny sterownik, który tego polecenia nie zna. Drugi błąd to mieszanie dialektów: SET NEW.kolumna = … i SIGNAL działają w MySQL, a w PostgreSQL potrzebne są NEW.kolumna := … i RAISE EXCEPTION.
Kolejny częsty błąd to próba modyfikacji wartości NEW w triggerze AFTER UPDATE. MySQL zgłasza wtedy błąd, a w PostgreSQL zmiana przechodzi bez skutku, bo wiersz jest już zapisany — kolumny ustawiaj wyłącznie w BEFORE. W PostgreSQL wyzwalacz BEFORE, który zwraca NULL zamiast NEW, po cichu pomija zapis wiersza. Nie ignoruj też wydajności: trigger FOR EACH ROW wykonuje się dla każdego wiersza, więc przy imporcie dużego zbioru może znacznie wydłużyć operację. W PostgreSQL wyzwalacz można na czas migracji wyłączyć (ALTER TABLE … DISABLE TRIGGER), w MySQL trzeba go usunąć i utworzyć ponownie.
Najczęstsze pytania
Jak zobaczyć istniejące triggery?
W MySQL: SHOW TRIGGERS; lub SHOW TRIGGERS LIKE 'users';. W obu bazach działa zapytanie do information_schema.triggers; gotowe polecenia dla nazwy z formularza są w ściądze pod generatorem.
Czy generator obsługuje PostgreSQL?
Tak. Dla PostgreSQL powstaje od razu funkcja zwracająca typ trigger i wyzwalacz z EXECUTE FUNCTION. Ta składnia działa od PostgreSQL 11; w starszych wersjach zamień ją na EXECUTE PROCEDURE.
Czy mogę wygenerować trigger dla wielu zdarzeń?
Generator obsługuje jedno zdarzenie na raz. MySQL i tak wymaga osobnego wyzwalacza dla INSERT, UPDATE i DELETE, a w PostgreSQL możesz ręcznie zmienić linię na np. BEFORE INSERT OR UPDATE ON tabela.
Jak usunąć trigger?
W MySQL: DROP TRIGGER IF EXISTS nazwa; (bez ON tabela). W PostgreSQL: DROP TRIGGER IF EXISTS nazwa ON tabela;, a wywoływaną funkcję usuwa się osobno przez DROP FUNCTION fn_nazwa();.
Czy trigger może modyfikować tę samą tabelę?
W MySQL nie: UPDATE lub INSERT na tabeli wyzwalacza kończy się błędem 1442, a bieżący wiersz zmienia się w BEFORE przez SET NEW.kolumna. PostgreSQL na to pozwala, ale każda taka zmiana ponownie uruchamia wyzwalacze tabeli, więc łatwo o nieskończoną pętlę.
Czy generator obsługuje triggery INSTEAD OF dla widoków?
Nie, narzędzie tworzy wyzwalacze BEFORE i AFTER dla tabel. INSTEAD OF trzeba napisać ręcznie: obsługuje je PostgreSQL dla widoków, a MySQL nie ma takiego rodzaju wyzwalaczy.