Единственный способ, которым вы «передаете перехваченную команду UPDATE на сервер после проверки столбцов», - это выполнить самостоятельно UPDATE
.
Вариант 1 - ROLLBACK
Однако вы сейчас сказали, что вы не хотите, чтобы добавить несколько столбцов в триггере, когда эти столбцы добавляются в таблицу. Таким образом, у вас есть альтернативный вариант просто отменить любые изменения, которые недействительны. Это может выглядеть примерно так:
CREATE TRIGGER TR_Sample_U ON dbo.Sample -- No AFTER trigger needed here!
AS
IF EXISTS (--check for disallowed modifications
SELECT *
FROM
Inserted I
INNER JOIN Deleted D
ON I.SampleID = D.SampleID
WHERE
I.Something <> D.Something
AND I.UpdateDate = D.UpdateDate
)
ROLLBACK TRAN;
Вариант 2 - Выполнение UPDATE в триггер
Однако, если вам нужно больше контроля над тем, что на самом деле влечет за собой обновление, например, необходимости изменить значение, прежде чем оно было совершено , вам нужно будет выполнить обновление самостоятельно. Например:
CREATE TRIGGER TR_Sample_U ON dbo.Sample
INSTEAD OF UPDATE
AS
SET NOCOUNT ON;
SET XACT_ABORT ON;
UPDATE S
SET S.Value = I.Value + '+'
FROM
dbo.Sample S
INNER JOIN Inserted I
ON S.SampleID = I.SampleID
;
Это тривиальный пример, который не делает никаких проверок, но вы получите идею - при выполнении обновления на Sample
таблицы, вы увидите, что значение приобретает дополнительный +
character - ваше обновление было перехвачено, а значение Inserted
(представляющее предлагаемое изменение после обновления) было изменено до его совершения.
See a SQL Fiddle Demo настоящего в действии.
Единственное, что нужно следить за это рекурсии:
Прямая рекурсия
Когда обновление может вызвать другие триггеры для запуска, которые модифицируют одну базовую таблицу - то вы можете получить пинг- между ними, пока не будет достигнут максимальный уровень гнезда, и вся транзакция будет отброшена назад.Поэтому имейте в виду возможное пинг-понг между триггерами.
Косвенное Рекурсия
Вы, вероятно, не придется беспокоиться об этом, потому что database-level RECURSIVE TRIGGERS
option отключена по умолчанию в SQL Server. Однако, если он включен, вы можете получить тот же запуск триггера, основываясь на новом обновлении.
Они уменьшалось в, по-разному:
TRIGGER_NESTLEVEL
Проверка внутри триггера, а выход триггера, если уже вложены достаточно глубоко.
Чтобы избежать прямой рекурсии, объедините триггеры.
В некоторых случаях, когда стратегическое назначение триггера запускается первым/последним, может возникнуть проблема. Вы не можете указать абсолютный порядок, но вы можете выбрать первый и последний.
Обратите внимание, что проблема пинг-понг относится к любому типу триггера, INSTEAD OF
или AFTER
, который изменяет свою собственную базовую таблицу, или участвует в цепочке обновлений через другой таблицы (которая имеет триггер, который изменяет другая таблица ...), которая в конечном итоге возвращается, чтобы изменить базовую таблицу.
Вариант 2B - предварительный запуск триггера ПОСЛЕ ОБНОВЛЕНИЯ.
Я называю эту опцию 2B, потому что это действительно вариант 2, но с улучшением. Если вы не хотите вручную обновлять триггер каждый раз, когда вы добавляете столбцы в таблицу (это я полностью согласен), вы можете автоматизировать это. Создайте хранимую процедуру, которая может создать соответствующий триггер, который соблюдает все необходимые проверки. Вы можете поместить базовый код для этой проверки в таблицу, затем в SP выберите его в переменные, добавьте скрипт SQL, обновляющий столбцы для окончательного обновления, используя информацию в представлении INFORMATION_SCHEMA.COLUMNS
, а затем, наконец, перезапишите триггер. Кроме того, это можно было бы подключить к триггеру DDL, так что он будет на 100% автоматизирован: вы должны добавить или удалить столбец из базовой таблицы, запускать DDL-триггер и переписать триггер DML для вас.
Это звучит очень много, но если вы разработали его для управления данными, его можно было бы обобщить для работы с любой таблицей во всей базе данных, что может иметь большое значение, в зависимости от ваших сценариев использования.
Что это значит, что это не соответствует тому, что сделано для стола? Вы прекращаете его переписывать в таблицу, перехватывая «ОБНОВЛЕНИЕ», но вложенные записи должны быть обновлены в таблице, если вы не перехватили их. Похоже, вам нужен триггер 'FOR UPDATE'. –
@ Love2Learn Я понимаю, что перехватываю команду update. Я ищу способ проверить данные, прежде чем они когда-либо сделают это в базе данных. Я хочу проверить вставленные/удаленные таблицы, а затем зафиксировать действие, отправленное на сервер на основе определенных условий. Я отредактирую код, чтобы быть более понятным. – user2255459