#sql-server #triggers #transactions
#sql-сервер #триггеры #транзакции
Вопрос:
У меня есть триггер после обновления таблицы, и в одной транзакции есть 2 обновления. Триггер был вызван после первого обновления. Я ожидаю, что запуск обновлений просмотра после всей транзакции, но это неверно:
Моя транзакция:
- обновить таблицу
- вызов триггера, триггер видит обновление только с 1
- обновить таблицу
- нет триггера вызова, потому что условие обновления в 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 по- прежнему не поддерживает переносимые ограничения, незарегистрированные таблицы, наследование таблиц и так далее.