SSDT 不考虑触发器启用/禁用属性



我已经从现有数据库创建了一个SSDT项目。它在表名.sql文件中包含现有触发器。

CREATE TABLE [dbo].[TableName] (
[ID]        INT           NULL
)
GO
CREATE TRIGGER trgTableName ON dbo.TableName
FOR INSERT 
AS
BEGIN
....
END
GO
DISABLE TRIGGER [dbo].[trgTableName] ON [dbo].[TableName]; /* My trigger is currently disabled */
GO

但是,每当我修改触发器时,SSDT 都会再次启用它。它在部署时不考虑触发器禁用属性。

无论如何,我可以让 SSDT 禁用触发器(如果它已经在数据库上禁用(?

我正在考虑的方法之一是添加为部署后脚本。但是,最好为此使用现有的 SSDT 功能,而不是手动添加部署后脚本。

编辑:如果我们更新它们,SQL服务器似乎会自动启用触发器。就我而言,触发器有更新,因此它可以启用触发器。但是,SSDT 在更新后不会禁用它。

一种方法当然是将其移动到PostDeploy。但我建议创建一个存储过程:

CREATE PROCEDURE mysp_disable_triggers
AS
BEGIN
DISABLE TRIGGER [dbo].[trgTableName] ON [dbo].[TableName];
END;

并在部署后脚本中调用它:

EXEC mysp_disable_triggers;

这样你就有一个单点引用,并且你的代码仍然被验证(检查引用是否存在,它是一个正确的SQL代码(。


要检查的第二种方法是使用ALTER TABLE语法:

CREATE TABLE [dbo].[TableName](...);
GO
CREATE TRIGGER [dbo].[trgTableName] ...;
GO
ALTER TABLE [dbo].[trgTableName] DISABLE TRIGGER [dbo].[TableName];

编辑:它不会改变行为。因此,PostDeploy apporach似乎是可行的选择。

如果你有一个难以管理的大型数据库,并且有很多这样的东西,你可能会变得棘手,并创建一个过程,编写一个脚本来捕获触发器状态并还原它们的过程。可以在"预部署"中运行该过程,然后在"部署后"中运行生成的过程。像这样:

create procedure dbo.scriptResetDisableTriggers as 
begin
set nocount on
declare 
@sql nvarchar( max ),
@n nvarchar( 2 ) = nchar(0x0d) + nchar(0x0a)
select @sql =  
N'create procedure dbo.resetDisabledTriggers as' + @n +
N'begin' + @n +
N'  set nocount on' + @n + @n;
select @sql += 
N'  begin try' + @n +
N'    disable trigger ' +  tr.name + N' on table ' + s.name + N'.' +    t.name + @n +
N'  end try' + @n +
N'  begin catch' + @n +
N'    print( error_message( ) ) -- or something else cool' + @n +
N'  end catch' + @n + @n
from 
sys.triggers tr
inner join
sys.tables t
on
tr.parent_id = t.object_id
inner join
sys.schemas s
on
t.schema_id = s.schema_id
where
tr.is_disabled = 1
select @sql +=  
@n + N'  drop procedure dbo.resetDisabledTriggers' + @n +
@n + N'end' + @n
print ( @sql )
execute sp_executesql  @sql
end

最新更新