当前位置:  开发笔记 > 编程语言 > 正文

SQL Server 2005:T-SQL暂时禁用触发器

如何解决《SQLServer2005:T-SQL暂时禁用触发器》经验,为你挑选了5个好方法。

是否可以禁用一批命令的触发器,然后在批处理完成后启用它?

我确信我可以放下触发器并重新添加它,但我想知道是否还有其他方法.



1> Matt Rogish..:
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



2> kristof..:

有时为了从外部数据源填充空数据库或调试数据库中的问题,我需要禁用所有触发器和约束.为此,我使用以下代码:

要禁用所有约束和触发器:

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> HLGEM..:

但是,这样做几乎总是一个坏主意.你会搞乱数据库的完整性.如果没有考虑分支并检查dbas,请不要这样做.

如果您遵循马特的代码,请务必记住重新打开触发器.并且记住,每个人在关闭表时插入,更新或删除表都会禁用触发器,而不仅仅是因为你的进程,所以如果必须这样做,那么在数据库最不活跃的时候这样做(最好是在单用户模式下).

如果您需要执行此操作以导入大量数据,请考虑批量插入不会触发触发器.但是,批量插入后的过程将不得不修复您引入的任何数据完整性问题,也不必触发触发器.



4> Daniel Imms..:

为了扩展Matt的答案,这是MSDN上给出的一个例子.

USE AdventureWorks;
GO
DISABLE TRIGGER Person.uAddress ON Person.Address;
GO
ENABLE Trigger Person.uAddress ON Person.Address;
GO



5> crokusek..:

另一种方法是使用包含在触发器中的附加状态变量来有效地禁用触发器而不实际禁用它.

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

一个潜在的主要缺点是触发器会根据访问状态变量的复杂性而永久性地减慢.

编辑:添加对Samuel Vanga这篇惊人相似的2008年帖子的引用.

推荐阅读
贾志军
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有