#sql-server #sql-server-2005 #tsql
Вопрос:
Можно ли отключить триггер для пакета команд, а затем включить его, когда пакет будет выполнен?
Я уверен, что мог бы сбросить курок и добавить его заново, но мне было интересно, есть ли другой способ.
Ответ №1:
DISABLE TRIGGER { [ schema_name . ] trigger_name [ ,...n ] | ALL }
ON { object_name | DATABASE | ALL SERVER } [ ; ]
http://msdn.microsoft.com/en-us/library/ms189748(SQL.90).aspx
за этим следует обратное:
ENABLE TRIGGER { [ schema_name . ] trigger_name [ ,...n ] | ALL }
ON { object_name | DATABASE | ALL SERVER } [ ; ]
http://msdn.microsoft.com/en-us/library/ms182706(SQL.90).aspx
Комментарии:
1. Спасибо! Я думаю, что моя наивность SQL Server 2005 слишком хорошо проявляется на этом сайте.
2. Не беспокойтесь; будьте администратором базы данных в течение длительного времени, и эти вещи станут автоматическими 🙂
3. т. е. если вы используете опцию для изменения триггера, а сценарий содержит
ALTER TRIGGER [dbo].[trgWhatever] ON [dbo].[tblWhatever]
, то вам нужноDISABLE TRIGGER [dbo].[trgWhatever] ON [dbo].[tblWhatever]
иENABLE TRIGGER [dbo].[trgWhatever] ON [dbo].[tblWhatever]
4. ПРИМЕЧАНИЕ — я получаю ошибку «Неправильный синтаксис рядом с «ОТКЛЮЧИТЬ». » если я не помещу
;
междуPRINT 'Some message'; DISABLE TRIGGER [dbo].....
Ответ №2:
Иногда, чтобы заполнить пустую базу данных из внешнего источника данных или отладить проблему в базе данных, мне нужно отключить ВСЕ триггеры и ограничения. Для этого я использую следующий код:
Чтобы отключить все ограничения и триггеры:
sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"
sp_msforeachtable "ALTER TABLE ? DISABLE TRIGGER all"
Чтобы включить все ограничения и триггеры:
exec sp_msforeachtable @command1="print '?'", @command2="ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
sp_msforeachtable @command1="print '?'", @command2="ALTER TABLE ? ENABLE TRIGGER all"
Я нашел это решение некоторое время назад на SQLServerCentral, но мне нужно было изменить часть «Включить ограничения», так как исходное решение не работало полностью
Ответ №3:
Однако делать это почти всегда плохая идея. Вы нарушите целостность базы данных. Не делайте этого, не рассмотрев последствия и не сверившись с базами данных, если они у вас есть.
Если вы будете следовать коду Мэтта, обязательно не забудьте снова включить триггер. И помните, что триггер отключен для всех, кто вставляет, обновляет или удаляет из таблицы, пока он выключен, а не только для вашего процесса, поэтому, если это необходимо сделать, делайте это в часы, когда база данных наименее активна (и предпочтительно в однопользовательском режиме).
Если вам нужно сделать это для импорта большого объема данных, учтите, что массовая вставка не запускает триггеры. Но тогда вашему процессу после массовой вставки придется устранять любые проблемы с целостностью данных, которые вы создадите, не активируя триггеры.
Комментарии:
1. Отличные моменты. Причина, по которой мне это было нужно, заключалась в том, что при копировании данных из производственной среды в тестовую среду некоторые АК сбрасывались триггером, но связанные столбцы в другой таблице не соответствовали этому.
Ответ №4:
Чтобы расширить ответ Мэтта, вот пример, приведенный на MSDN.
USE AdventureWorks;
GO
DISABLE TRIGGER Person.uAddress ON Person.Address;
GO
ENABLE Trigger Person.uAddress ON Person.Address;
GO
Ответ №5:
Другой подход состоит в том, чтобы эффективно отключить триггер, фактически не отключая его, используя дополнительную переменную состояния, которая включена в триггер.
create trigger [SomeSchema].[SomeTableIsEditableTrigger] ON [SomeSchema].[SomeTable]
for insert, update, delete
as
declare
@isTableTriggerEnabled bit;
exec usp_IsTableTriggerEnabled -- Have to use USP instead of UFN for access to #temp
@pTriggerProcedureIdOpt = @@procid,
@poIsTableTriggerEnabled = @isTableTriggerEnabled out;
if (@isTableTriggerEnabled = 0)
return;
-- Rest of existing trigger
go
Для переменной состояния можно прочитать некоторую запись управления блокировкой в таблице (лучше всего, если она ограничена контекстом текущего сеанса), использовать CONTEXT_INFO () или использовать наличие определенного имени временной таблицы (которое уже ограничено областью действия сеанса).:
create proc [usp_IsTableTriggerEnabled]
@pTriggerProcedureIdOpt bigint = null, -- Either provide this
@pTableNameOpt varchar(300) = null, -- or this
@poIsTableTriggerEnabled bit = null out
begin
set @poIsTableTriggerEnabled = 1; -- default return value (ensure not null)
-- Allow a particular session to disable all triggers (since local
-- temp tables are session scope limited).
--
if (object_id('tempdb..#Common_DisableTableTriggers') is not null)
begin
set @poIsTableTriggerEnabled = 0;
return;
end
-- Resolve table name if given trigger procedure id instead of table name.
-- Google: "How to get the table name in the trigger definition"
--
set @pTableNameOpt = coalesce(
@pTableNameOpt,
(select object_schema_name(parent_id) '.' object_name(parent_id) as tablename
from sys.triggers
where object_id = @pTriggerProcedureIdOpt)
);
-- Else decide based on logic involving @pTableNameOpt and possibly current session
end
Затем, чтобы отключить все триггеры:
select 1 as A into #Common_DisableTableTriggers;
-- do work
drop table #Common_DisableTableTriggers; -- or close connection
Потенциально серьезным недостатком является то, что триггер постоянно замедляется в зависимости от сложности доступа к переменной состояния.
Правка: Добавление ссылки на этот удивительно похожий пост 2008 года Сэмюэля Ванги.
Ответ №6:
ALTER TABLE table_name DISABLE TRIGGER TRIGGER_NAME
-- Here your SQL query
ALTER TABLE table_name ENABLE TRIGGER TRIGGER_NAME
Ответ №7:
Не лучший ответ для пакетного программирования, но для тех, кто ищет этот вопрос в поисках быстрого и простого способа временного отключения триггера, это можно сделать в среде SQL Server Management Studio.
- разверните папку триггеры в таблице
- щелкните правой кнопкой мыши на триггере
- отключать
Выполните тот же процесс для повторного включения.