SQL Server: запуск после транзакции

#sql-server #triggers #transactions

#sql-сервер #триггеры #транзакции

Вопрос:

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

Моя транзакция:

  1. обновить таблицу
  2. вызов триггера, триггер видит обновление только с 1
  3. обновить таблицу
  4. нет триггера вызова, потому что условие обновления в 3 не соответствует

Можно установить триггер, а затем запустить просмотр данных после транзакции (как с 1, так и с 3)?

Мой триггер:

 ALTER TRIGGER "dbo"."TRIGGER" 
ON TABLE
FOR UPDATE
AS
    IF (SELECT COUNT(*) FROM inserted i, deleted d
        WHERE d.aaa IS NULL 
          AND i.aaa IS NOT NULL 
          AND i.bbb IN ('0', '1', '6', '9')) > 0
    BEGIN
        INSERT INTO export (aaa, ccc) 
            (SELECT aaa, ccc FROM inserted)
    END
  

Инициализация данных: insert into TABLE(aaa,bbb,ccc) values(123,'N',100)

Обновления:

 update TABLE set bbb = '0' where aaa = 123
update TABLE set ccc = 1 where aaa = 123
  

Ожидать: insert into export(123,1)

Но он вызывает: insert into export(123,100)

Комментарии:

1. Пожалуйста, обратите внимание, что триггер в SQL Server является set-based . Таким образом, он будет выполнять свои действия для всего набора (обновления) одновременно. Можете ли вы поделиться кодом из своего триггера и проверить, правильно ли он обрабатывает этот подход, основанный на множествах?

2. ваш вопрос неясен. я предполагаю, что вы спрашиваете .. you have two updates in one transaction and you want your trigger to be called for second update only on same table ?

3. Если (3) не приводит к дальнейшим изменениям в таблице, то таблица, как она наблюдалась в триггере в (2), такая же, как и в (4). Я не понимаю, в чем проблема.

4. Запуск триггера выполняется только после первого обновления. Все в порядке. Но в этой транзакции существует другое обновление, которое обновляет данные. Я хочу, чтобы триггер видел новые данные (если триггер находится в транзакции).

5. Похоже, что есть проблема с примером кода, потому что первое обновление (где aaa = 123) не будет удовлетворять условию внутри триггера (где удалено. aaa равно нулю), поэтому он не будет вставляться в экспорт ни в первый, ни во второй раз.

Ответ №1:

Я вижу вашу проблему.

Однако триггеры в SQL Server находятся на уровне оператора, к сожалению, они работают не так, как вы ожидаете здесь. Вероятно, вы могли бы заставить его работать, добавив в таблицу некоторый столбец «control» (обновив его в самом конце транзакции и создав вокруг него некоторую логику) или используя context_info, но это действительно пахнет IMHO.

Отойдите от триггера и выполните вставку в таблицу экспорта из основной области, это ваш лучший вариант.

Комментарии:

1. Подобные вещи начинают заставлять меня задуматься об использовании Postgres для моего следующего проекта — в Postgres сейчас так много функций моделирования данных и приложений, что SQL Server выглядит очень устаревшим… например, сейчас 2021 год, а SQL Server по- прежнему не поддерживает переносимые ограничения, незарегистрированные таблицы, наследование таблиц и так далее.