Триггеры — специальные объекты базы данных, которые автоматически запускают выполнение определённого кода (обычно на SQL или языках процедурных расширений, например PL/pgSQL для PostgreSQL) при наступлении события: INSERT, UPDATE или DELETE на таблице.
Преимущества:
Недостатки:
Когда применять:
Пример триггера (PostgreSQL):
CREATE TABLE employee_audit ( id SERIAL PRIMARY KEY, employee_id INT, old_salary NUMERIC, new_salary NUMERIC, changed_at TIMESTAMP ); CREATE OR REPLACE FUNCTION audit_salary() RETURNS TRIGGER AS $$ BEGIN IF NEW.salary <> OLD.salary THEN INSERT INTO employee_audit(employee_id, old_salary, new_salary, changed_at) VALUES (OLD.id, OLD.salary, NEW.salary, NOW()); END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER trg_salary_update AFTER UPDATE ON employees FOR EACH ROW EXECUTE FUNCTION audit_salary();
Можно ли внутри триггера обновить ту же таблицу, на которую он установлен? Что произойдет?
Ответ:
Если триггер настроен на событие, скажем, UPDATE таблицы и внутри себя выполняет ещё один UPDATE этой же таблицы, это приведёт к возникновению бесконечной рекурсии (зацикливанию) и аварийному завершению команды или ошибке превышения глубины триггеров. Поэтому всегда контролируйте, чтобы не возникала рекурсия, или используйте опции, разрешающие/запрещающие рекурсивные вызовы.
Пример:
-- Такой конструкцией можно зациклить триггер: CREATE OR REPLACE FUNCTION recursive_update() RETURNS TRIGGER AS $$ BEGIN UPDATE employees SET salary = salary * 1.01 WHERE id = NEW.id; -- сработает снова RETURN NEW; END; $$ LANGUAGE plpgsql;
История
В бухгалтерской CRM внедрили триггер для автоматической записи операций в лог при изменении таблицы транзакций. Под высокой нагрузкой сервис стал работать медленнее, а анализ показал: триггер тратит много времени на вставку в лог и не был оптимизирован (например, не писал только существенные события).
История
В проекте управления инвентаризацией использовался BEFORE INSERT триггер для расчёта ID позиции. Неправильная логика ID провоцировала дублирование данных, причём ошибка долго оставалась незамеченной, потому что работала "за кадром".
История
В HR-платформе триггер делал массовое обновление записей в родительской и дочерней таблицах при каждом INSERT. Из-за ошибок в логике триггера возникла рекурсия, что полностью блокировало все операции с таблицами. Пришлось отключить триггер и сделать сложную rollback-митацию для разблокирования таблиц.