Триггер на таблицу

Синтаксис

Триггер на вход

Синтаксис

Как написать триггер

Конспект
Триггер - это специальный вид хранимых процедур, которые выполняются на определенные события в таблице. Триггер связывается с определенной таблицей
События
Существуют три события, на которые могут реагировать триггеры:
- Вставка
INSERT - Обновление
UPDATE - Удаление
DELETEИдеален для обеспечения целостности и согласованности данных, но работает медленнее, чем стандартные огранчения
Создание триггера
синтаксис
CREATE TRIGGER trigger_name
ON { table | view }
[ WITH ENCRYPTION ]
{
{ { FOR | AFTER | INSTEAD OF } { [ INSERT ] [ , ] [ UPDATE ] }
[ WITH APPEND ]
[ NOT FOR REPLICATION ]
AS
[ { IF UPDATE ( column )
[ { AND | OR } UPDATE ( column ) ]
[ ...n ]
| IF (COLUMNS_UPDATED() {bitwise_operator} updated_bitmask)
{ comparison_operator } column_bitmask [ ...n ]
} ]
sql_statement [ ...n ]
}
}Нельзя создать триггер на системные таблицы
Ограничения
Сервер SQL не позволяет использовать следующие операторы в теле триггера:
ALTER DATABASECREATE DATABASEDISK INITDISK RESIZE;DROP DATABASELOAD DATABASELOAD LOGRECONFIGURERESTORE DATABASERESTORE LOGт.е. в них нельзя изменять структуру базы данных
Откат изменений в триггере
Объявление триггера может содержать оператор ROLLBACK TRANSACTION, который откатит все изменения в таблице, на которой вызвался триггер
пример создания триггера
CREATE TRIGGER u_tbPeoples ON dbo.tbPeoples
FOR UPDATE
AS
ROLLBACK TRANSACTIONКак работают триггеры?
INSERT
- Пользователем выполняется оператор
INSERTдля добавления записей - Сервер сохраняет информацию о запросе в журнале транзакций
- Вызывается триггер
- Подтверждение изменений и физическое изменение данных Во время вызова триггера, физического изменения в базе еще не произошло. В теле триггера вы можете увидеть добавляемые записи в виде таблицы inserted Таблица inserted всегда имеет такую же структуру, что и у таблицы, на которую установлен триггер
пример
CREATE TRIGGER i_tbPeoples ON dbo.tbPeoples
FOR INSERT
AS
DECLARE @Name varchar(50)
SELECT @Name=vcName
FROM inserted
IF @Name='ВАСЯ'
BEGIN
PRINT 'ОШИБКА'
ROLLBACK TRANSACTION
ENDDELETE
- Пользователем выполняется оператор
DELETEдля добавления записей - Сервер сохраняет информацию о запросе в журнале транзакций
- Вызывается триггер с таблицей deleted
- Подтверждение изменений и физическое изменение данных Особенности:
- когда строки добавляются в таблицу deleted, они еще существуют в таблице базы данных
- для таблицы deleted выделяется память, поэтому она всегда в кэше
- триггер удаления не выполняется на операцию
TRUNCATE TABLE
Пример
CREATE TRIGGER d_tbPeoples ON dbo.tbPeoples
FOR DELETE
AS
IF EXISTS (SELECT *
FROM deleted
WHERE vcName='рлр')
BEGIN
PRINT 'ОШИБКА, нельзя удалить этого пользователя'
ROLLBACK TRANSACTION
ENDТриггеры срабатывают после проверки всех ограничений CHECK и внешних ключей
UPDATE
Обновление - по сути два этапа – удаление и вставка. Поэтому в триггера на обновление 2 таблицы: deleted и inserted
Можно мониторить только некоторые колонки с помощью IF UPDATE:
CREATE TRIGGER u_tbPeoples ON dbo.tbPeoples
FOR UPDATE
AS
IF UPDATE (vcName)
PRINT 'Я надеюсь, что вы правильно указали имя'Если нужно выполнить несколько операторов в триггере, то объедините их с помощью BEGIN и END:
CREATE TRIGGER u_tbPeoples ON dbo.tbPeoples
FOR UPDATE
AS
IF UPDATE (vcName)
OR UPDATE (vcFamil)
OR UPDATE (vcSurname)
BEGIN
PRINT 'Нельзя изменять фамилию, имя и отчество'
ROLLBACK TRANSACTION
ENDINSTEAD OF
Действия такого триггера выполняются вместо операторов, сгенерировавших триггер
Каждая таблица или просмотрщик ограничены одним триггером INSTEAD OF на каждое событие
Как можно использовать INSTEAD OF?
Допустим, что у нас есть объект просмотра, который выбирает данные их двух таблиц. Как мы уже знаем, данные вьюшки можно изменять, только если все они принадлежат одной таблице. Но с помощью триггера можно сделать обновление любого количества таблиц
CREATE TRIGGER i_People ON dbo.People
INSTEAD OF INSERT
AS
BEGIN
-- Добавление должности
INSERT INTO tbPosition (vcPositionName)
SELECT vcPositionName
FROM inserted i
-- Добавление работника
INSERT INTO tbPeoples (vcFamil, idPosition)
SELECT vcFamil, idPosition
FROM inserted i,tbPosition pn
WHERE i.vcPositionName=pn.vcPositionName
ENDОбновление представления с помощью триггера
CREATE TRIGGER u_People ON dbo.People
INSTEAD OF UPDATE
AS
BEGIN
UPDATE tbPosition
SET vcPositionName=i.vcPositionName
FROM tbPosition pn, inserted i
WHERE i.idPosition=pn.idPosition
UPDATE tbPeoples
SET vcFamil=i.vcFamil
FROM tbPeoples pl, inserted i
WHERE i.idPeoples=pl.idPeoples
ENDВы должны учитывать, что в таблицу может вставляться сразу несколько строк. Вы должны учитывать это при написании триггеров, как мы это делали при создании примеров с использованием INSTEAD OF
Владелец таблицы может использовать процедуру sp_settriggerorder для указания первого выполняемого триггера и последнего
Триггеры не должны возвращать результирующих наборов
Хранение истории
Очень часто в базах данных необходимо сохранять историю. Можно делать с помощью триггера
Особенности триггеров
Триггеры могут иметь вложения до 32 уровней
Вложенный триггер не будет вызываться дважды в одной транзакции, триггер не вызывает сам себя в ответ на второе обновление к одной и той же таблицы. Для примера, если триггер изменяет таблицу, которая по цепочке изменяет оригинальную таблицу, триггер не вызывается снова.
Включение рекурсивных вызовов триггеров
ALTER DATABASE FlenovSQLBook SET RECURSIVE_TRIGGERS ON