Как я могу сделать до обновления триггер с сервером SQL? - PullRequest
38 голосов
/ 13 марта 2009

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

Ответы [ 8 ]

35 голосов
/ 13 марта 2009

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

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

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

32 голосов
/ 07 января 2011

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

8 голосов
/ 19 января 2016

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

В таблице удалено хранятся копии затронутых строк во время удаления и ОБНОВЛЕНИЕ заявления. Во время выполнения УДАЛЕНИЯ или ОБНОВЛЕНИЯ оператор, строки удаляются из таблицы триггеров и передаются в удаленная таблица ...

В таблице вставлен хранятся копии затронутых строк во время INSERT и ОБНОВЛЕНИЕ заявления. Во время вставки или обновления транзакции, новый строки добавляются как во вставленную таблицу, так и в таблицу триггеров ...

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

8 голосов
/ 13 марта 2009

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

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

3 голосов
/ 13 марта 2009

Все «нормальные» триггеры в SQL Server являются триггерами «AFTER ...». Триггеров "ДО ..." нет.

Чтобы сделать что-то перед обновлением, посмотрите Триггеры INSTEAD OF UPDATE .

2 голосов
/ 03 мая 2012

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

2 голосов
/ 13 марта 2009

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

0 голосов
/ 26 марта 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
...