SQL Server 2005: T-SQL для временного отключения триггера - PullRequest
50 голосов
/ 24 сентября 2008

Можно ли отключить триггер для пакета команд, а затем включить его после завершения пакета?

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

Ответы [ 7 ]

62 голосов
/ 24 сентября 2008
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

32 голосов
/ 24 сентября 2008

Иногда, чтобы заполнить пустую базу данных из внешнего источника данных или отладить проблему в базе данных, мне нужно отключить ВСЕ триггеры и ограничения. Для этого я использую следующий код:

Чтобы отключить все ограничения и триггеры:

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 , но мне нужно было изменить часть разрешающих ограничений, поскольку исходная часть не работала полностью

15 голосов
/ 24 сентября 2008

Однако это почти всегда плохая идея. Вы будете связываться с целостностью базы данных. Не делайте этого без учета последствий и проверки с помощью dbas, если они у вас есть.

Если вы действительно следуете коду Мэтта, не забудьте снова включить триггер. И помните, что триггер отключен для всех, кто вставляет, обновляет или удаляет из таблицы, пока он выключен, а не только для вашего процесса, поэтому, если это необходимо сделать, делайте это в часы, когда база данных наименее активна (и предпочтительно в однопользовательском режиме).

Если вам нужно сделать это, чтобы импортировать большой объем данных, учтите, что при массовой вставке триггеры не запускаются. Но тогда ваш процесс после массовой вставки должен будет исправить любые проблемы с целостностью данных, которые вы вводите, или запустить триггеры.

11 голосов
/ 04 июля 2013

Чтобы расширить ответ Мэтта, вот пример, приведенный на MSDN .

USE AdventureWorks;
GO
DISABLE TRIGGER Person.uAddress ON Person.Address;
GO
ENABLE Trigger Person.uAddress ON Person.Address;
GO
5 голосов
/ 03 октября 2013

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

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 от Samuel Vanga .

3 голосов
/ 19 августа 2016
ALTER TABLE table_name DISABLE TRIGGER TRIGGER_NAME
-- Here your SQL query
ALTER TABLE table_name ENABLE TRIGGER TRIGGER_NAME
2 голосов
/ 09 сентября 2017

Не лучший ответ для пакетного программирования, но для тех, кто ищет этот вопрос в поисках быстрого и простого способа временного отключения триггера, это можно сделать в SQL Server Management Studio.

  1. развернуть папку триггеров на столе
  2. щелкните правой кнопкой мыши триггер
  3. отключить

enter image description here

Для повторного включения выполните тот же процесс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...