Как я могу сделать до обновления триггер с сервером SQL?
Я использую Sqlserver Express и не могу before updated
спусковой крючок. Есть другой способ сделать это?
7 ответов
MSSQL не поддерживает BEFORE
триггеры. Ближайший у вас есть INSTEAD OF
триггеры, но их поведение отличается от BEFORE
триггеры в MySQL.
Вы можете узнать о них больше здесь, и обратите внимание, что INSTEAD OF
triggers "Указывает, что триггер выполняется вместо триггерного оператора SQL, таким образом переопределяя действия триггерных операторов". Таким образом, действия по обновлению могут не выполняться, если триггер неправильно записан / обработан. Каскадные действия также затрагиваются.
Вместо этого вы можете использовать другой подход к тому, чего вы пытаетесь достичь.
Это правда, что в MSSQL нет "до запуска". Однако вы все равно можете отслеживать изменения, внесенные в таблицу, используя вместе "вставленные" и "удаленные" таблицы. Когда обновление вызывает срабатывание триггера, в "вставленной" таблице хранятся новые значения, а в "удаленной" - старые. Получив эту информацию, вы можете относительно легко смоделировать поведение "до запуска".
Не могу быть уверен, что это применимо к SQL Server Express, но вы все равно можете получить доступ к данным "до", даже если ваш триггер происходит после обновления. Вам необходимо прочитать данные из удаленной или вставленной таблицы, которая создается на лету при изменении таблицы. По сути, это то, что говорит @Stamen, но мне все еще нужно было продолжить изучение, чтобы понять этот (полезный!) Ответ.
В удаленной таблице хранятся копии затронутых строк во время операторов DELETE и UPDATE. Во время выполнения оператора DELETE или UPDATE строки удаляются из таблицы триггеров и переносятся в удаленную таблицу...
Вставленная таблица хранит копии затронутых строк во время операторов INSERT и UPDATE. Во время транзакции вставки или обновления новые строки добавляются как во вставленную таблицу, так и в таблицу триггеров...
Таким образом, вы можете создать триггер для чтения данных из одной из этих таблиц, например:
CREATE TRIGGER <TriggerName> ON <TableName>
AFTER UPDATE
AS
BEGIN
INSERT INTO <HistoryTable> ( <columns...>, DateChanged )
SELECT <columns...>, getdate()
FROM deleted;
END;
Мой пример основан на следующем:
T-SQL поддерживает только триггеры AFTER и INSTEAD OF, в нем нет триггера BEFORE, как в некоторых других РСУБД.
Я полагаю, что вы захотите использовать триггер INSTEAD OF.
Все "нормальные" триггеры в SQL Server являются триггерами "AFTER ...". Нет триггеров "ДО..."
Чтобы сделать что-то перед обновлением, проверьте триггеры INSTEAD OF UPDATE.
Обновленные или удаленные значения хранятся в DELETED. мы можем получить его с помощью метода ниже в триггере
Полный пример,
CREATE TRIGGER PRODUCT_UPDATE ON PRODUCTS
FOR UPDATE
AS
BEGIN
DECLARE @PRODUCT_NAME_OLD VARCHAR(100)
DECLARE @PRODUCT_NAME_NEW VARCHAR(100)
SELECT @PRODUCT_NAME_OLD = product_name from DELETED
SELECT @PRODUCT_NAME_NEW = product_name from INSERTED
END
Помните, что когда вы используете триггер вместо этого, он не будет фиксировать вставку, если вы не указали это в триггере. Вместо того, чтобы действительно означать, делайте это вместо того, что вы обычно делаете, так что ни одно из обычных действий вставки не произойдет.
Сделать BEFORE UPDATE
в SQL Server я использую трюк. Я делаю ложное обновление записи (UPDATE Table SET Field = Field
), таким образом я получаю предыдущее изображение записи.
Полный пример:
CREATE TRIGGER [dbo].[trig_020_Original_010_010_Gamechanger]
ON [dbo].[T_Original]
AFTER UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @Old_Gamechanger int;
DECLARE @New_Gamechanger int;
-- Insert statements for trigger here
SELECT @Old_Gamechanger = Gamechanger from DELETED;
SELECT @New_Gamechanger = Gamechanger from INSERTED;
IF @Old_Gamechanger != @New_Gamechanger
BEGIN
INSERT INTO [dbo].T_History(ChangeDate, Reason, Callcenter_ID, Old_Gamechanger, New_Gamechanger)
SELECT GETDATE(), 'Time for a change', Callcenter_ID, @Old_Gamechanger, @New_Gamechanger
FROM deleted
;
END
END