Триггер (database trigger) — хранимая процедура в СУБД, выполняемая автоматически при наступлении определённого события на таблице: INSERT, UPDATE или DELETE. В отличие от хранимой процедуры, триггер нельзя вызвать напрямую — он срабатывает только как реакция на DML-операцию. Это механизм обеспечения целостности данных и автоматизации рутинных действий на уровне СУБД.
Типы триггеров
- BEFORE: выполняется до применения операции. Позволяет изменить или отклонить вставляемые/обновляемые данные. В MySQL BEFORE-триггер может менять
NEW.field. - AFTER: выполняется после успешной операции. Обычно используется для аудита, логирования, обновления агрегатов в других таблицах.
- INSTEAD OF: заменяет операцию полностью. Поддерживается в PostgreSQL и SQL Server для представлений (views).
- По событию: INSERT, UPDATE, DELETE. Можно комбинировать:
BEFORE INSERT OR UPDATE.
Пример триггера PostgreSQL
CREATE FUNCTION update_modified()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER set_updated_at
BEFORE UPDATE ON orders
FOR EACH ROW EXECUTE FUNCTION update_modified();
При каждом UPDATE на таблице orders автоматически обновляется поле updated_at без изменений в коде приложения.
История
Концепция триггеров появилась в Ingres в конце 1970-х. IBM DB2 добавил триггеры в 1989 году. Oracle поддерживает триггеры с версии 6.0 (1988). SQL Server — с версии 6.0 (1995). MySQL добавил триггеры в версии 5.0 (2005). PostgreSQL поддерживает триггеры с версии 6.x (1996), включая строчные (row-level) и операторные (statement-level). Стандарт SQL:2003 формализовал синтаксис триггеров.
Где применяют триггеры
- Автоматическое обновление полей:
updated_at,modified_by - Аудит изменений: копирование строк в таблицу аудита при изменении
- Валидация данных сложнее, чем CHECK-constraint
- Обновление агрегатов: счётчик комментариев в таблице постов
- Каскадные операции, не описанные через FOREIGN KEY
На что обращать внимание
Триггеры скрыты от кода приложения — поведение базы данных становится неочевидным. При отладке проблем с данными всегда проверяй наличие триггеров: в MySQL — SHOW TRIGGERS FROM dbname, в PostgreSQL — SELECT * FROM information_schema.triggers. Не используй триггеры для бизнес-логики, которая должна быть в приложении: они усложняют перенос на другую СУБД и тестирование. При большой нагрузке (INSERT 1000+ строк/с) триггеры добавляют задержку — профилируй с EXPLAIN ANALYZE.
История триггеров в СУБД
Триггеры появились в стандарте SQL-92 и первыми были реализованы в Sybase SQL Server и Oracle в конце 1980-х годов. MySQL добавил поддержку триггеров в версии 5.0.2 (2004). PostgreSQL поддерживает триггеры с версии 7.0 (2000), позволяя писать функции-триггеры на PL/pgSQL, PL/Python, PL/Perl. SQL Server и Oracle поддерживают DDL triggers — реакция на CREATE/ALTER/DROP, что позволяет протоколировать изменения схемы.
Триггеры для аудита данных
Распространённый паттерн — таблица аудита с триггером, записывающим старые и новые значения при каждом UPDATE:
CREATE TABLE orders_audit (
id SERIAL PRIMARY KEY,
order_id INT,
old_status VARCHAR(50),
new_status VARCHAR(50),
changed_at TIMESTAMPTZ DEFAULT NOW()
);
Триггер INSERT INTO orders_audit срабатывает только при изменении статуса. Это распространённый способ реализации audit trail без изменения кода приложения. Аналогичный паттерн — таблица updated_at: BEFORE UPDATE-триггер устанавливает NEW.updated_at = NOW() автоматически.
На что обращать внимание
Триггеры могут образовывать каскады: триггер на таблице A вставляет в B, триггер на B обновляет C. Это снижает прозрачность и усложняет отладку. При переносе базы через дамп триггеры включаются по умолчанию — проверьте, что при восстановлении они не сработают нежелательно. Проверить триггеры: в MySQL — SHOW TRIGGERS FROM dbname, в PostgreSQL — SELECT * FROM information_schema.triggers WHERE trigger_schema='public'. Не используй триггеры для бизнес-логики приложения — усложняет тестирование и перенос на другую СУБД.