To, že v těle triggeru nemohu volat upravovat původní tabulku skrze DML mi přijde spíš jako výhoda než nevýhoda. Dost často se setkávám s tím, že programátoři si nevšimnou rozdílů mezi T-SQL a zbytem světa a triggery píší podle vzoru T-SQL. Což je samosebou špatně – v případě MySQL, PostgreSQL nebo Oraclu či DB2. V MySQL je tento přístup přímo zakázán – u ostatních databází vede k rekurzi (ve výsledku je to pomalé nebo se db chová „podivně“).
Je potřeba se MySQL v tomto případě zastat a říct, že MySQL má triggery navržené správně (v tomto ohledu – pak jsou další libůstky jako třeba práva), hlavně ovšem JINAK než MS-SQL server. MS SQL má používá primárně a pouze statement triggery, ostatní databáze row triggery – jenomže zvyk je železná košile :(.
Co tak sleduji MySQL, tak problémy s VIEW a neexistencí SIGNALu by měly být vyřešené v 5.5, která teď aktuálně vyšla. Zkoušel jí někdo?
Já vím pouze o jediném modelu, kdy v z update triggeru chci aktualizovat jiné záznamy – a tím jsou nested sets – což je Celkova implementace stromů. O žádném dalším nevím. Osobně, pokud bych zrovna nehackoval běžící aplikaci, kdy není šance psát slušný kód, bych se rekurzivně volaným triggerům vyhnul obloukem – u běžné aplikace (přestože pg s tím nemá problém). Zrovna implementace triggerů v MS Serveru – riziko rekurze, byl důvod proč se v podstatě v 90 letech docela dost zásadně nedoporučovalo používání triggerů.
V DB2 v after triggerech muzete bezproblemu upravovat jakoukoliv tabulku, klidne i tu nad kterou je trigger definovan:
CREATE TRIGGER MAJITEL.POKUSTEST AFTER INSERT ON MAJITEL.POKUS REFERENCING NEW AS NEWROW NEW_TABLE AS NTABLE FOR EACH ROW MODE DB2SQL
BEGIN ATOMIC
DELETE FROM MAJITEL.POKUS POKUS
WHERE POKUS.ID = 25;
END
proc by to mela databaze zakazovat? pro ni je trigger inline funkce jako kazda jina. db2 umi row i statement level trigery.
Psal jsem o něčem jiném. Jako hlavní riziko vidím programátory, kteří nepochopili smysl proměnných NEW a OLD, a jsou schopní napsat např. UPDATE trigger jako
BEGIN
UPDATE tab SET col = current_time
WHERE id = OLD.id;
END;
je to dost zjednodušené pro názornost.
Už jsem to psal, teď trochu jinými slovy. I když většina databází umožňuje umístit do triggerů DML příkazy – osobně se snažím spíš preferovat procedury před triggery. AFTER triggery beru primárně pouze pro kontroly (a případně jednoduché logování). Není to dáno technologickým omezením – až na MySQL většina db nemá toto omezení, jako spíš snahou nebudovat black box, kdy DML příkazem startujete nějaký monstrózní proces. Monstrózní procesy mám ráději izolované v procedurách než schované v triggerech.