Я работаю на SQL Server 2008 R2.
У меня есть табличное преимущество, которое имеет триггер AFTER INSERT, UPDATE с именем tiu_benefit .
Я хочу написать инструкцию UPDATE для этой таблицы, чтобы обновить 1 строку, но я не хочу, чтобы ее триггер срабатывал. Я знаю, что могу отключить триггер до UPDATE, а затем включить триггер после UPDATE:
DISABLE TRIGGER tiu_benefit ON benefit;
GO
UPDATE benefit SET editor = 'srh' where benefit_id = 9876
GO
ENABLE TRIGGER tiu_benefit ON benefit;
GO
Но это отключение и включение триггера повлияет на всех пользователей, вошедших в данный момент. Так что есть вероятность, что другой пользователь запустит UPDATE / INSERT, пока мой скрипт не отключит триггер, что не очень хорошо. Вот почему я хочу только отключить и включить триггер для моей текущей сессии. Является ли это возможным? Если да, пожалуйста, расскажите как.
Благодарность
Ответы:
Я провел некоторое тестирование по этому вопросу, и я думаю, что все будет в порядке, если вы запустите свой процесс в одной транзакции.
В моем тестировании я только выделил и выполнил
BEGIN TRANSACTION
иDISABLE TRIGGER
первый. Затем я открыл новый (второй) окно запроса и попытался запустить различные заявления DML (SELECT
,INSERT
,UPDATE
DELETE
) против базовой таблицы. Все попытки доступа к базовой таблице во втором окне запроса ожидали блокировок, удерживаемых окном с явной транзакцией. Когда я зафиксировал (или откатил) свою явную транзакцию, второе окно смогло получить доступ к таблице.источник
benefit_id
:)Чтобы решить вашу проблему, мы должны принять программный подход к проблеме. Есть два маршрута, по которым вы можете пойти здесь. Причина, по которой эти подходы нужны, заключается в том, что вы не можете отключить триггер для определенного оператора, его можно отключить только для всей таблицы.
Вариант 1: Context_Info ()
У Самуэля Ванги на MS SQL Tips был отличный пример:
Теперь, когда Самуил не хочет, чтобы триггер выполнялся, они используют это:
Context_Info
использует следующие системные представления для получения информации о текущем сеансе:sys.dm_exec_requests
sys.dm_exec_sessions
sys.sysprocesses
Идеология здесь заключается в том, что двоичная строка, которую вы устанавливаете, доступна только для текущего сеанса, поэтому, когда триггер выполняется во время вашего сеанса, он увидит область действия и настройку переменной
Context_info
функции и перейдет к escape-части триггера. вместо.Вариант 2: временная таблица
У Ицик Бен-Гана есть отличное решение в его книге «Внутри Microsoft SQL Server 2008 Программирование на T-SQL: Программирование на T-SQL», а также в его более поздней книге « Запросы на T-SQL» . Основная проблема с этим по
context_info
функции - незначительные издержки TempDB.Чтобы испортить сюрприз, но не разрушить сюжет книг (я чувствовал, что их стоит покупать и читать), вы измените свой триггер.
Ваш триггер должен выполнить проверку для временной таблицы. Если временная таблица существует, триггер должен знать, что нужно завершить, а не выполнять действия.
В операторе обновления, который вы хотите выполнить, сначала создайте временную таблицу. Он будет отображаться в той же транзакции, что и триггер, и он будет игнорировать ваш оператор.
Пример триггера:
Пример начального оператора, когда вы не хотите запускать триггер:
В целом это для вашего примера:
источник
context_info
использованию,original_login()
чтобы сказать триггеру никогда не запускаться, если конкретный человек нажимает на триггер.Я бы использовал либо
CONTEXT_INFO
новый, либо новыйSESSION_CONTEXT
. Оба значения основаны на сеансах.CONTEXT_INFO
это одноVARBINARY(128)
значение. Это было доступно по крайней мере с SQL Server 2000. ДоступноCONTEXT_INFO
для просмотра любому пользователю, такVIEW SERVER STATE
как это поле возвращаетсяsys.dm_exec_sessions
DMV. Я использовал это раньше, и он работает довольно хорошо.Установить через SET CONTEXT_INFO
Получить через CONTEXT_INFO () или sys.dm_exec_sessions
В зависимости от типа значения, которое вы храните
CONTEXT_INFO
, есть некоторые нюансы, о которых нужно знать. Я расскажу об этом в следующем сообщении в блоге:Почему CONTEXT_INFO () не возвращает точное значение, установленное SET CONTEXT_INFO?
Session_context является парой ключ / значение
SQL_VARIANT
. Это было введено в SQL Server 2016. Разделение значений для разных целей довольно приятно. Session_context доступен только для просмотра текущего сеанса.Установите это значение с помощью sp_set_session_context.
Получите это значение с помощью SESSION_CONTEXT.
Следует учитывать одну вещь, касающуюся опции локальной временной таблицы и даже опции триггера отключения / включения: обе из них требуют некоторого количества блокировок и активности журнала. Оба этих варианта увеличивают вероятность возникновения конфликтов, даже если они минимальны. Два параметра «контекста» должны иметь меньший вес / только память.
источник