Проверка факта изменения конкретных столбцов
В теле триггера insert или update с помощью особой проверки if update (имя-столбца) можно выяснить, обновлен ли конкретный столбец таблицы. Следующий пример показывает, как это делается:
CREATE TRIGGER TrackDiscountUpdates
ON AppDta.dbo.Customer FOR UPDATE
AS IF UPDATE(Discount)
INSERT INTO AppDta.dbo.CustUpdLog (Custld, Action, Discount, UpdUser, UpdDateTime)
SELECT Custld, ‘Update’, Discount, CURRENT_USER, CURRENT_TIMESTAMP FROM INSERTED
ENDIF
Так же как в обычной структуре if. . .else. . .endif, в инструкции if update можно использовать логические операторы and и or, объединяющие несколько условий. Например:
CREATE TRIGGER TrackCustomerUpdates
ON AppDta.dbo.Customer FOR UPDATE
AS IF UPDATE(Name) AND UPDATE(Discount) ...
CREATE TRIGGER TrackCustomerUpdates
ON AppDta.dbo.Customer FOR UPDATE
AS IF UPDATE( Name ) OR UPDATE( Discount ) ...
Примечание. SQL Server позволяет помещать проверку условия if update (имя-столбца) прямо за ключевым словом as и без ключевого слова endif. В этом случае все тело триггера выполняется при условии, что заданный столбец обновлен. Однако мы рекомендуем использовать стандартный синтаксис if update (имя-столбца) ...endif и рассматривать update (имя-столбца) как обычную логическую функцию.
Для инструкции update проверка update (имя-столбца) возвращает True, если столбец указан в предложении set. SQL Server не проверяет, действительно ли его новое значение отличается от старого. Для инструкции insert проверка update (имя-столбца) возвращает True, если столбец явно указан в списке столбцов этой инструкции или если список столбцов в ней вообще отсутствует (что неявно означает "все столбцы"). И не имеет значения, каким образом столбцу присвоено новое значение: задано ли оно как литерал, как выражение или вместо значения задано ключевое слово null или default.
Дополнительные опции триггеров
В инструкции create trigger могут использоваться две необязательные опции. Первая из них, with encryption, шифрует сохраняемый в системном каталоге код триггера:
CREATE TRIGGER TrackCustomerUpdates
ON AppDta.dbo.Customer WITH ENCRYPTION FOR UPDATE AS ...
Для того чтобы при модификации данных процессом репликации триггер не вызывался, нужно включить в его определение опцию not for replication:
CREATE TRIGGER TrackCustomerUpdates
ON AppDta.dbo.Customer FOR UPDATE
NOT FOR REPLICATION AS ...
Изменение и удаление триггеров
Для изменения определения триггера используется инструкция alter trigger. Можно просто удалить триггер и создать его заново. Удаление триггера выполняется так:
DROP TRIGGER TrackCustomerUpdates
Инструкция alter TRIGGER имеет точно такой же синтаксис, что и инструкция create TRIGGER, за исключением первого ключевого слова.
Включение и отключение триггера
Инструкция alter table позволяет включать и отключать отдельные триггеры таблицы. Отключение триггера выполняется так:
ALTER TABLE Customer
DISABLE TRIGGER TrackCustomerUpdates
Для того чтобы снова включить триггер, повторите эту инструкцию, заменив ключевое слово DISABLE ключевым словом enable. Можно включать и отключать все триггеры сразу, заменив имя триггера ключевым словом all.
Работа с триггерами
Для одной таблицы можно создавать несколько триггеров, более того, их может быть несколько даже для одной и той же инструкции (например UPDATE). Каждая новая инструкция CREATE TRIGGER связывает с таблицей еще один триггер в дополнение к уже существующим. Когда вызывается инструкция, с которой связано несколько триггеров, для членов которой не определен конкретный порядок, все они выполняются по очереди. Единственное, что можно сделать в отношении последовательности их выполнения, это указать, какой из триггеров должен запускаться первым, а какой — последним. Для этого используется системная хранимая процедура sp_settriggerorder:
sp_settriggerorder ‘TrackCustomerUpdates’, ‘First’, ‘Update’
У процедуры sp_settriggerorder три аргумента: имя триггера, порядок его выполнения (First, Last или None – первый, последний или порядок не определен) и тип инструкции (INSERT, update или DELETE). Если триггер связан с двумя или тремя инструкциями, нужно выполнить процедуру sp_settriggerorder для каждой инструкции, для которой вы хотите задать порядок его выполнения. После окончания инструкции ALTER TRIGGER порядок выполнения измененного триггера устанавливается в None, т.е. снова становится неопределенным.
Таким образом, если более двух триггеров таблицы связано с одной и той же операцией, порядок выполнения всех этих триггеров задать нельзя. А потому при написании этих триггеров не рассчитывайте на определенную последовательность их выполнения, т.е. не основывайте действия одного триггера на результатах выполнения другого. Эта особенность выполнения триггеров не так уж важна, поскольку в случае, когда необходимо разбить триггер на несколько отдельных модулей, всегда можно написать несколько обыкновенных хранимых процедур и по очереди вызывать их из триггера. В этом случае в порядке их выполнения можно быть уверенным.
Триггер всегда создается в той же базе данных, что и таблица, с которой он связан. В пределах базы данных имена триггеров должны быть уникальны. При желании можно уточнить имя триггера именем владельца (например, dbo. TrackCustomerUpdates), но владельцем триггера может быть только владелец таблицы.
Примечание. Хотя триггер всегда связан с базовой таблицей из той же базы данных, в которой хранится он сам, в нем могут быть ссылки на объекты из других баз данных. Это позволяет создавать триггеры, обеспечивающие целостность связей между двумя таблицами из разных баз данных. Внешние ключи, определяемые в инструкции CREATE TABLE, этого не позволяют.
Несмотря на то, что триггер является разновидностью хранимой процедуры, его нельзя вызывать с помощью инструкции EXECUTE. Если какой-то программный код должен совместно использовать триггеры и обычные хранимые процедуры или просто несколько триггеров, поместите его в хранимую процедуру и вызывайте из этих триггеров.