S prstem na spoušti spouštíme spouště, aneb MySQL, triggery a praxe.
25.11.2005 06:00 | Petr Zajíc | přečteno 45291×
V minulém dílu jsme si řekli dost o teorii triggerů, takže je čas podívat se na to, jak je můžeme v MySQL použít v praxi. Na jednu stranu to bude trochu smutné čtení, protože MySQL triggery zdaleka neumějí to, co triggery třebas ve Firebirdu. Na druhou stranu je ale i tak život se spouštěmi veselejší než bez nich.
Uvedli jsme, že triggery mohou přispívat k bezpečnosti dat a že jedním z příkladů může být "bezpečné" mazání řádků v tabulce. Bezpečné proto, že záznam není vymazán úplně, ale data jsou přesunuta do jiné tabulky, takže je později lze dohledat. Pokud tedy budeme mít následující tabulku:
create table bezpecna
(id int not null auto_increment, jmeno varchar( 50 ) not null, plat
decimal(12,4) not null, primary key (id)) type = myisam;
S testovacími daty:
insert into bezpecna
(jmeno, plat) values ('Jarda', 12000);
insert into bezpecna (jmeno, plat) values ('Pepa', 13000);
insert into bezpecna (jmeno, plat) values ('Franta', 14000);
insert into bezpecna (jmeno, plat) values ('Honza', 10000);
insert into bezpecna (jmeno, plat) values ('Anička', 11500);
můžeme chtít místo mazání z této tabulky data přesunout do "záložní" tabulky s tím, že si zároveň poznamenáme, kdo a kdy ta původní data promazával. Něco takového zcela určitě můžeme svěřit triggeru. Vytvoříme si tabulku, která bude obsahovat data z původní tabulky a ještě údaj o "mazajícím" uživateli a čase, kdy se řádky odstraňovaly:
create table
bezpecna_zaloha like bezpecna;
alter table bezpecna_zaloha add column cas_odstraneni datetime;
alter table bezpecna_zaloha add column uzivatel varchar (128);
a konečně, vytvoříme trigger, který při odstraňování dat ta původní data uchová v tabulkce bezpecna_zaloha:
create trigger
trSaveRows
before delete
on bezpecna
for each row
begin
insert into bezpecna_zaloha(id, jmeno, plat,
cas_odstraneni, uzivatel)
values (old.id, old.jmeno, old.plat, now(), user());
end;
Jaký je význam toho všeho? Výsledek spočívá v tom, že když se nyní pokusíte odstranit nějaká ta data z tabulky bezpecna, tak... vyzkoušejte postupně tyto příkazy:
delete from bezpecna
where id > 2;
select * from bezpecna;
select * from bezpecna_zaloha;
Jak vidíte, smazaná data se objeví v tabulkce bezpecna_zaloha. K tomu všemu bude
jistě vhodné uvést pár poznámek:
K příkladu ještě jedno varování: Trigger se NESPUSTÍ při použití
příkazu TRUNCATE TABLE. To není chyba, ale vlastnost DMBS, takže pokud
se spoléháte na nějakou akci, která se spustí při odstraňování dat z
tabulky, buďte opatrní. Při použití DELETE FROM TABLE se však trigger
spustí a zpracuje všechny řádky, které ještě v nebohé tabulce zbývají.
Další typickou činností triggerů je kontrola měněných dat. Mělo by tedy jít například napsat trigger, který do naší tabulky zakáže vkládat platy vyšší než 30000,- Kč. Vypadal by nějak takhle:
create trigger trMaxPlat
before insert
on bezpecna
for each row
begin
if new.plat>30000 then /*něco, co akci zruší*/;
end if;
end;
Bohužel, v době psaní tohoto článku je prakticky nemožné vyhodit nějakou smysluplnou chybu z triggeru, a to jejich použití pro kontrolu dat téměř znemožňuje. Pro informaci se můžete podívat do diskuse k tomuto tématu. Manuál doporučuje pro takový případ "uměle" vytvořit například chybu porušení primárního klíče, podle mě je to však jen chabá náplast. Problém je reportován do buglistu (sem a sem), tak uvidíme, co s tím bude vývojářský tým dělat.