Triggers
Stored procedures that automatically execute in response to INSERT, UPDATE, or DELETE operations on a table.
trigger CREATE TRIGGER BEFORE trigger AFTER trigger INSTEAD OF trigger row trigger statement trigger
trigger event automation audit DML BEFORE AFTER
| Database | Status | Syntax Family | Min Version |
|---|---|---|---|
| PostgreSQL | full | sql-standard | - |
| MySQL | full | sql-standard | - |
| MariaDB | full | sql-standard | - |
| Oracle | full | plsql | - |
| SQL Server | full | tsql | - |
| SQLite | full | sql-standard | - |
| Redshift | none | - | - |
| DB2 | full | sql-standard | - |
| Snowflake | none | - | - |
| BigQuery | none | - | - |
Compare Databases
Database Details
PostgreSQL
full
CREATE FUNCTION set_updated_at()
RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
NEW.updated_at := NOW();
RETURN NEW;
END;
$$;
CREATE TRIGGER trg_set_updated_at
BEFORE UPDATE ON orders
FOR EACH ROW
EXECUTE FUNCTION set_updated_at();- Trigger function must be created separately and return type trigger.
- Supports FOR EACH ROW and FOR EACH STATEMENT granularity.
- INSTEAD OF triggers work on views to make them updatable.
- DDL event triggers (CREATE EVENT TRIGGER) fire on DDL statements like CREATE TABLE.
- Transition tables (NEW TABLE, OLD TABLE) are available for statement-level triggers (v10+).
Docs: CREATE TRIGGER, Trigger Procedures
MySQL
full
CREATE TRIGGER trg_set_updated_at
BEFORE UPDATE ON orders
FOR EACH ROW
BEGIN
SET NEW.updated_at = NOW();
END;- Row-level triggers only - no statement-level trigger support.
- No INSTEAD OF triggers on views.
- No DDL triggers.
- Multiple triggers per event/timing combination supported since MySQL 5.7.
- NEW and OLD row references available in trigger body.
Docs: CREATE TRIGGER
MariaDB
full
CREATE TRIGGER trg_set_updated_at
BEFORE UPDATE ON orders
FOR EACH ROW
BEGIN
SET NEW.updated_at = NOW();
END;- Same capabilities as MySQL: BEFORE/AFTER row-level DML triggers.
- No statement-level or INSTEAD OF triggers.
- Sequence-aware triggers available in newer versions.
- Oracle-compatible trigger syntax available in sql_mode=ORACLE.
Docs: CREATE TRIGGER
Oracle
full
-- Row-level DML trigger
CREATE OR REPLACE TRIGGER trg_set_updated_at
BEFORE UPDATE ON orders
FOR EACH ROW
BEGIN
:NEW.updated_at := SYSDATE;
END;
/
-- DDL trigger
CREATE OR REPLACE TRIGGER trg_audit_ddl
AFTER CREATE ON SCHEMA
BEGIN
INSERT INTO ddl_log(event, obj)
VALUES(ORA_SYSEVENT, ORA_DICT_OBJ_NAME);
END;
/- Supports BEFORE, AFTER, and INSTEAD OF timing for DML.
- DDL triggers fire on CREATE, ALTER, DROP events at schema or database level.
- Database event triggers fire on STARTUP, SHUTDOWN, LOGON, LOGOFF, SERVERERROR.
- COMPOUND TRIGGER combines multiple timing points (BEFORE STATEMENT, BEFORE EACH ROW, etc.) in one object.
- FOLLOWS / PRECEDES clause controls ordering of multiple triggers on the same event.
Docs: CREATE TRIGGER
SQL Server
full
-- DML trigger (AFTER)
CREATE TRIGGER trg_set_updated_at
ON orders
AFTER UPDATE
AS BEGIN
UPDATE orders
SET updated_at = GETDATE()
FROM orders o
INNER JOIN inserted i ON o.id = i.id;
END;
-- DDL trigger
CREATE TRIGGER trg_audit_ddl
ON DATABASE
AFTER CREATE_TABLE
AS BEGIN
INSERT INTO ddl_log(event_type, event_data)
SELECT EVENTDATA().value('(/EVENT_INSTANCE/EventType)[1]','NVARCHAR(100)'),
CONVERT(NVARCHAR(MAX), EVENTDATA());
END;- No BEFORE triggers - only AFTER and INSTEAD OF.
- INSERTED and DELETED virtual tables contain the new and old row versions.
- DDL triggers fire at DATABASE or ALL SERVER scope.
- Logon triggers fire on user authentication events.
- EVENTDATA() function returns XML with DDL event details.
Docs: CREATE TRIGGER (T-SQL)
SQLite
full
CREATE TRIGGER trg_set_updated_at
AFTER UPDATE ON orders
FOR EACH ROW
WHEN NEW.updated_at = OLD.updated_at
BEGIN
UPDATE orders SET updated_at = datetime('now')
WHERE id = NEW.id;
END;- Supports BEFORE, AFTER, and INSTEAD OF timing.
- Row-level only - no statement-level triggers.
- INSTEAD OF triggers on views enable updatable views.
- WHEN clause provides conditional execution.
- OLD and NEW row references available.
Docs: CREATE TRIGGER
Redshift
none
- Redshift does not support triggers.
- Use Amazon EventBridge rules with Lambda for event-driven reactions to Redshift changes.
- Stored procedure polling can simulate some trigger-like behavior.
- Amazon Redshift Data API combined with scheduled queries provides an alternative.
DB2
full
CREATE TRIGGER trg_set_updated_at
BEFORE UPDATE ON orders
REFERENCING NEW AS n
FOR EACH ROW
BEGIN ATOMIC
SET n.updated_at = CURRENT TIMESTAMP;
END;- Supports BEFORE, AFTER, and INSTEAD OF timing.
- FOR EACH ROW and FOR EACH STATEMENT granularity.
- REFERENCING clause names the NEW and OLD row/table correlation names.
- Multiple trigger events (INSERT OR UPDATE OR DELETE) in one CREATE TRIGGER statement.
- Transition variables (NEW, OLD) and transition tables (NEW_TABLE, OLD_TABLE) available.
Docs: CREATE TRIGGER
Snowflake
none
- Snowflake does not support triggers.
- Snowflake Streams capture change data (CDC) on tables as an alternative.
- Snowflake Tasks can be scheduled or triggered by stream lag to process stream data.
- The Streams + Tasks pattern provides event-driven processing similar to triggers.
BigQuery
none
- BigQuery does not support triggers.
- Use Pub/Sub notifications on BigQuery table changes to invoke Cloud Functions or Cloud Run.
- Eventarc can route BigQuery events (job completion, table changes) to Cloud Functions.
- Scheduled queries can poll for changes on a recurring basis.