Триггер — это специальный тип хранимой процедуры, которая автоматически выполняется при возникновении определенного события в таблице (INSERT, UPDATE, DELETE). Триггеры привязаны к таблицам и активируются в ответ на изменения данных.
Автоматическое выполнение
Срабатывают без явного вызова при наступлении связанного события
Привязка к таблице
Создаются для конкретной таблицы или представления
Контекст выполнения
Работают в контексте транзакции, вызвавшей их
Доступ к специальным таблицам
INSERTED и DELETED - виртуальные таблицы с изменяемыми данными
Срабатывают после выполнения оператора DML
CREATE TRIGGER trg_AfterOrderInsert
ON Orders
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO OrderLog(OrderID, Action, LogDate)
SELECT i.OrderID, 'INSERT', GETDATE()
FROM inserted i;
END;
Заменяют оригинальную операцию, выполняют пользовательский код
CREATE TRIGGER trg_InsteadOfDelete
ON Customers
INSTEAD OF DELETE
AS
BEGIN
SET NOCOUNT ON;
-- Помечаем клиентов как неактивных вместо удаления
UPDATE Customers
SET IsActive = 0
WHERE CustomerID IN (SELECT CustomerID FROM deleted);
END;
Реагируют на события изменения структуры БД (CREATE, ALTER, DROP)
CREATE TRIGGER trg_PreventTableChanges
ON DATABASE
FOR DROP_TABLE, ALTER_TABLE
AS
BEGIN
ROLLBACK;
RAISERROR('Изменение структуры таблиц запрещено!', 16, 1);
END;
CREATE TRIGGER trg_AuditProductChanges
ON Products
AFTER UPDATE, DELETE
AS
BEGIN
INSERT INTO ProductAudit(ProductID, OldPrice, NewPrice, ChangeDate, Action)
SELECT
d.ProductID,
d.Price,
i.Price,
GETDATE(),
CASE WHEN d.ProductID IS NOT NULL AND i.ProductID IS NOT NULL THEN 'UPDATE'
ELSE 'DELETE' END
FROM deleted d
LEFT JOIN inserted i ON d.ProductID = i.ProductID;
END;
CREATE TRIGGER trg_DeleteCustomerOrders
ON Customers
AFTER DELETE
AS
BEGIN
DELETE FROM Orders
WHERE CustomerID IN (SELECT CustomerID FROM deleted);
END;
CREATE TRIGGER trg_ValidateOrder
ON Orders
AFTER INSERT, UPDATE
AS
BEGIN
IF EXISTS (
SELECT 1 FROM inserted i
JOIN Customers c ON i.CustomerID = c.CustomerID
WHERE i.TotalAmount > c.CreditLimit
)
BEGIN
ROLLBACK TRANSACTION;
RAISERROR('Превышен кредитный лимит клиента', 16, 1);
END
END;
Доступ к inserted и deleted
Вложенность триггеров
SQL Server поддерживает до 32 уровней вложенности
Рекурсия триггеров
Можно отключить: ALTER DATABASE SET RECURSIVE_TRIGGERS OFF
Порядок выполнения
Можно задать с помощью sp_settriggerorder
Не могут:
Следует избегать:
Отключение триггера:
DISABLE TRIGGER trg_AfterOrderInsert ON Orders;
Включение триггера:
ENABLE TRIGGER trg_AfterOrderInsert ON Orders;
Изменение триггера:
ALTER TRIGGER trg_AfterOrderInsert ON Orders
AS
BEGIN
-- Новый код
END;
Удаление триггера:
DROP TRIGGER trg_AfterOrderInsert;
Оптимизация производительности:
SET NOCOUNT ON
Обработка ошибок:
CREATE TRIGGER trg_SafeDelete
ON Products
INSTEAD OF DELETE
AS
BEGIN
BEGIN TRY
-- Логика триггера
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
THROW;
END CATCH
END;
Документирование:
CREATE TRIGGER trg_LogChanges
/*
Purpose: Логирование изменений в таблице Orders
Created: 2023-01-15
Author: DBA Team
*/
ON Orders
AFTER UPDATE
AS
BEGIN
-- Код триггера
END;
Резюмируем: триггеры в SQL Server — это мощный инструмент для автоматизации реакций на изменения данных, реализации сложных ограничений целостности и аудита. Однако их следует использовать осмотрительно, учитывая влияние на производительность и сложность отладки. Правильно спроектированные триггеры могут значительно упростить архитектуру приложения, перенеся критически важную логику на уровень базы данных.