Как я могу сделать триггер BEFORE UPDATED с сервером sql?

Я использую Sqlserver Express и не могу запустить before updated триггер. Есть другой способ сделать это?


person Bigballs    schedule 13.03.2009    source источник


Ответы (9)


MSSQL не поддерживает триггеры BEFORE. Самое близкое, что у вас есть, это INSTEAD OF триггеры, но их поведение отличается от поведения BEFORE триггеров в MySQL.

Подробнее о них можно узнать здесь, а также отметить что INSTEAD OF триггеры «Указывает, что триггер выполняется вместо триггерного оператора SQL, таким образом переопределяя действия триггерных операторов». Таким образом, действия по обновлению могут не выполняться, если триггер неправильно написан/обработан. Каскадные действия также затронуты.

Вместо этого вы можете использовать другой подход к тому, чего вы пытаетесь достичь.

person achinda99    schedule 13.03.2009

Это правда, что в MSSQL нет «до триггеров». Однако вы по-прежнему можете отслеживать изменения, внесенные в таблицу, используя таблицы «вставлено» и «удалено» вместе. Когда обновление вызывает срабатывание триггера, «вставленная» таблица сохраняет новые значения, а «удаленная» таблица сохраняет старые значения. Получив эту информацию, вы могли бы относительно легко смоделировать поведение «до запуска».

person Stamen    schedule 07.01.2011
comment
Это был ответ, который сработал для меня; таблица DELETED содержит исходное значение; таблица INSERTED содержит новое/обновленное значение. Отлично работает с ПОСЛЕ ОБНОВЛЕНИЯ. - person gimlichael; 19.05.2015
comment
В удаленной таблице хранятся копии затронутых строк во время операторов DELETE и UPDATE. Вставленная таблица сохраняет копии затронутых строк во время операторов INSERT и UPDATE. Транзакция обновления аналогична операции удаления, за которой следует операция вставки; старые строки сначала копируются в удаленную таблицу, а затем новые строки копируются в триггерную таблицу и во вставленную таблицу. - person csmith; 09.12.2016

Не могу быть уверен, что это применимо к SQL Server Express, но вы все равно можете получить доступ к данным «до», даже если ваш триггер происходит ПОСЛЕ обновления. Вам необходимо прочитать данные из таблицы deleted или inserted, которая создается на лету при изменении таблицы. По сути, это то, что говорит @Stamen, но мне все еще нужно было изучить этот (полезный!) ответ.

В таблице deleted хранятся копии затронутых строк во время операторов DELETE и UPDATE. Во время выполнения инструкции DELETE или UPDATE строки удаляются из триггерной таблицы и переносятся в удаляемую таблицу...

Таблица inserted хранит копии затронутых строк во время операторов INSERT и UPDATE. Во время транзакции вставки или обновления новые строки добавляются как во вставленную таблицу, так и в таблицу триггера...

https://msdn.microsoft.com/en-us/library/ms191300.aspx

Таким образом, вы можете создать свой триггер для чтения данных из одной из этих таблиц, например.

CREATE TRIGGER <TriggerName> ON <TableName>
AFTER UPDATE
AS
  BEGIN
    INSERT INTO <HistoryTable> ( <columns...>, DateChanged )
    SELECT <columns...>, getdate()
    FROM deleted;
  END;

Мой пример основан на приведенном здесь:

http://www.seemoredata.com/en/showthread.php?134-Example-of-BEFORE-UPDATE-trigger-in-Sql-Server-good-for-Type-2-dimension-table-updates

sql-server триггеры

person Charlie Joynt    schedule 19.01.2016
comment
Если бы не опоздание на 7 лет. ;-) - person Charlie Joynt; 15.06.2017
comment
Это должен быть правильный ответ. - person Edgar Froes; 29.03.2018

T-SQL поддерживает только триггеры AFTER и INSTEAD OF, в нем нет триггера BEFORE, как в некоторых других СУБД.

Я полагаю, вы захотите использовать триггер INSTEAD OF.

person Ian Nelson    schedule 13.03.2009

Все "обычные" триггеры в SQL Server являются триггерами "ПОСЛЕ...". Триггеров "ДО..." нет.

Чтобы сделать что-то перед обновлением, проверьте ВМЕСТО ОБНОВЛЕНИЯ Триггеры.

person Tomalak    schedule 13.03.2009

Чтобы сделать BEFORE UPDATE в SQL Server, я использую трюк. Делаю ложное обновление записи (UPDATE Table SET Field = Field), таким образом получаю предыдущее изображение записи.

person Luciano    schedule 03.05.2012

Помните, что когда вы используете триггер вместо этого, он не зафиксирует вставку, если вы специально не укажете это в триггере. Вместо того, чтобы действительно означает сделать это вместо того, что вы обычно делаете, чтобы не произошло ни одно из обычных действий вставки.

person HLGEM    schedule 13.03.2009
comment
Это следует поместить как комментарий к существующему ответу, а не как сам ответ. - person TroySteven; 18.06.2019

Полный пример:

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
person Nick Oetjen    schedule 26.03.2019
comment
Я не уверен, насколько этот ответ актуален, когда OP запрашивает обновление до обновления. - person KMC; 25.07.2019
comment
С моей точки зрения, есть две причины, по которым вам может понадобиться триггер «До»: а) остановить действие б) сделать что-то с данными до того, как они будут изменены и, следовательно, могут быть потеряны. Для а) вы бы предпочли использовать другой способ, например, проверку согласованности в хранимой процедуре. Для б) можно использовать предложенный код - по крайней мере я так делал и почему наткнулся на эту тему. - person Nick Oetjen; 26.07.2019
comment
Сравните ответ Лучано от 3 мая 2012 г. - person Nick Oetjen; 26.07.2019

Обновленные или удаленные значения сохраняются в 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
person Lenin    schedule 13.07.2020