启用细节触发器,Sql Server

时间:2014-01-24 15:22:26

标签: sql sql-server sql-server-2008 triggers

我遇到的情况是我必须禁用所有触发器并启用它们才能加速特定的备份工作。 我使用下面的代码禁用所有我的触发器

EXEC sp_msforeachtable "ALTER TABLE ? DISABLE TRIGGER ALL"
GO

我使用object_id和最初禁用的所有触发器的名称保留了一个表#InitiallyDesabledTR(object_ID, Name)

Create Table #InitiallyDesabledTR(Object_id int, name varchar (45))
Insert into #InitiallyDesabledTR(Object_id, name)
(
    SELECT object_id, name
    FROM sys.triggers tr
    WHERE tr.is_disabled = 1

    )

是否有人知道如何重新启用我的数据库中存在的所有触发器,但临时表#InitiallyDesabledTR上的触发器除外。

2 个答案:

答案 0 :(得分:0)

这将禁用尚未禁用的所有表触发器,然后仅重新启用已禁用的表触发器。在SQL Server 2008 R2中测试过。我没有使用临时表来跟踪最初禁用的触发器,而是更改为使用物理表dbAdmin_TriggersToReEnable来跟踪作为工作一部分被禁用的触发器。这可以确保如果作业因某些原因因触发器被禁用而失败但在重新启用之前,那么您仍然需要重新启用仍然需要重新启用的触发器列表。下一次运行。使用原始设置,如果您禁用了所有触发器,然后在备份作业处理期间出现错误,则所有触发器将保持禁用状态,并且您将丢失对最初因为临时表而被禁用的触发器的引用, #InitiallyDesabledTR,将会消失。

设置:创建表格dbo.dbAdmin_TriggersToReEnable,以及2个存储过程dbo.spDbAdmin_DisableAllTableTriggersdbo.spDbAdmin_ReEnableTriggers

if not exists(select 1 from sys.tables t where t.name = 'dbAdmin_TriggersToReEnable')
    create table dbo.dbAdmin_TriggersToReEnable(
        object_id int not null, 
        parent_id int not null, 
        triggerName sysname not null, 
        tableSchemaName sysname not null, 
        tableName sysname not null,
        creationdate datetime
        , constraint PK_dbAdmin_TriggersToReEnable  PRIMARY KEY CLUSTERED (object_id)
    );
go

CREATE PROC dbo.spDbAdmin_DisableAllTableTriggers
AS
BEGIN
    set nocount on;

    INSERT INTO dbo.dbAdmin_TriggersToReEnable(object_id, parent_id, triggerName, tableSchemaName, tableName, creationdate)
    SELECT tr.object_id, tr.parent_id, tr.name AS triggerName, schema_name(tbl.schema_id) as tableSchemaName, tbl.name as tableName, getdate() as creationdate
    FROM sys.triggers tr
        INNER JOIN sys.tables tbl on tbl.object_id = tr.parent_id
        LEFT JOIN dbo.dbAdmin_TriggersToReEnable e on tr.object_id = e.object_id 
    WHERE tr.is_disabled = 0
        AND e.object_id is null --not already in the table
    ;

    --disable all triggers
    EXEC sp_msforeachtable 'ALTER TABLE ? DISABLE TRIGGER ALL'

END
GO

CREATE PROC dbo.spDbAdmin_ReEnableTriggers
AS
BEGIN
    declare @object_id int, @schemaName nvarchar(256), @tableName nvarchar(256), @triggerName nvarchar(3000), @sql nvarchar(max);

    select @object_id = min(e.object_id) from dbo.dbAdmin_TriggersToReEnable e;

    while exists(select 1 from dbo.dbAdmin_TriggersToReEnable)
    begin
        select @schemaName = t.tableSchemaName, @tableName = t.tableName, @triggerName = t.triggerName
        from dbo.dbAdmin_TriggersToReEnable t
        where t.object_id = @object_id
        ;

        set @sql = 'ALTER TABLE ' + QUOTENAME(@schemaName) + '.' + QUOTENAME(@tableName) + ' ENABLE TRIGGER ' + QUOTENAME(@triggerName) ;

        EXEC(@sql);

        delete t from dbo.dbAdmin_TriggersToReEnable t where t.object_id = @object_id;
        select @object_id = min(t.object_id) from dbo.dbAdmin_TriggersToReEnable t;
    end;

END
GO

然后您可以使用以下步骤设置SQL代理作业:

--Step 1
EXEC dbo.spDbAdmin_DisableAllTableTriggers;

--Step 2
--....do your backup job work here...

--Step 3
EXEC dbo.spDbAdmin_ReEnableTriggers;

答案 1 :(得分:0)

我必须禁用所有索引,触发器和约束以加快备份速度。 即使采取这样的行动,通过执行接近900行代码,这种备份需要超过15个小时。 我没有可能使用级联进行删除,这就是为什么我必须检查初始表和所有实例之间的所有完整性。 PS。我备份的唯一标准是创建订单的日期。