VillageSQL is a drop-in replacement for MySQL with extensions.
All examples in this guide work on VillageSQL. Install Now →
Creating a Trigger
BEFORE vs AFTER
A
BEFORE INSERT trigger can set default values or reject bad data. An AFTER INSERT trigger can write audit records after the insert succeeds.
NEW and OLD References
Modify
NEW values in a BEFORE trigger to change what gets written:
Multiple Triggers Per Event
MySQL supports multiple triggers on the same table and event. TheFOLLOWS and PRECEDES keywords control execution order:
FOLLOWS/PRECEDES, MySQL assigns execution order based on creation time.
Raising Errors in Triggers
UseSIGNAL to abort the operation and return an error to the caller:
BEFORE trigger signals an error, the insert/update/delete is aborted — nothing is written.
Trigger Limitations
MySQL triggers have several restrictions worth knowing:- Triggers cannot call stored procedures that return result sets
- Triggers cannot use
COMMIT,ROLLBACK, orSAVEPOINTdirectly (they participate in the surrounding transaction) - Triggers cannot reference the table they’re defined on (no recursive trigger calls via direct queries on the same table in most contexts)
AFTERtriggers cannot modifyNEWvalues — the row is already written- MySQL does not support statement-level triggers (every trigger is
FOR EACH ROW)
When to Use Triggers
Triggers work well for:- Audit logging — capturing who changed what and when, regardless of application
- Enforcing complex constraints that CHECK constraints can’t express
- Keeping derived data in sync (denormalized summary columns, audit timestamps)
- The logic is complex enough that debugging it requires tracing hidden side effects
- Performance is critical — every trigger fires per row, on every affected statement
- The trigger modifies data in a way that surprises application developers unaware of its existence
Frequently Asked Questions
Do triggers fire during LOAD DATA INFILE?
Yes.INSERT triggers fire for each row loaded by LOAD DATA INFILE. If your trigger does significant work, bulk-loading through LOAD DATA will be much slower than loading into a staging table first, then copying with INSERT…SELECT (which also fires triggers, but you can temporarily disable them with SET @disable_trigger = TRUE and a conditional check inside the trigger).
Can triggers call stored procedures?
Yes, with one exception: the called procedure cannot return a result set (aSELECT without INTO). If it does, MySQL returns an error. Procedures called from triggers can use OUT parameters and SELECT...INTO.
Do triggers fire on REPLACE INTO?
REPLACE executes as a DELETE + INSERT when there’s a conflict. On conflict: BEFORE DELETE, AFTER DELETE, BEFORE INSERT, and AFTER INSERT triggers all fire on the target table. ON DELETE CASCADE rules on related tables do NOT fire from a REPLACE.
Troubleshooting
See also
- Stored Procedures in MySQL — logic that triggers can call
- Sending Webhooks from Triggers — HTTP calls from trigger bodies
- CHECK Constraints in MySQL — a simpler alternative for validation rules that triggers often implement

