【问题标题】:SSDT does not consider trigger enable/disable propertySSDT 不考虑触发器启用/禁用属性
【发布时间】:2020-06-04 14:18:38
【问题描述】:

我从现有数据库创建了一个 SSDT 项目。它包括 tablename.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 不会在更新后禁用它。

【问题讨论】:

  • 刚刚提到,在导入数据库后,我们将触发器定义移动到它们自己的文件中。这使它们更易于管理。没有任何残疾人,所以无法帮助解决这个问题。
  • 没问题,我想我也会这样做 - 这是更清洁的方法。
  • 我已经记不清有多少微妙的issues within SSDT 导致了意想不到的结果。我喜欢所需状态部署的想法,但最终像这样的边缘情况会导致我们放弃 SSDT。
  • 能否检查一下部署属性的状态:忽略 DML 触发器状态?
  • @DavidRushton 您可能使用了错误的论坛来提出 SSDT 问题。您应该尝试使用 Visual Studio 将这些问题提交到他们的developer community 以获得更快的响应。

标签: sql-server sql-server-data-tools


【解决方案1】:

一种方法当然是将其移至 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 似乎是可行的选择。

【讨论】:

  • 感谢您的回复。那么,这是否意味着它是 SSDT / Visual Studio 中的一个错误,它无法检测到触发器已被禁用,即使它已被修改,它也应该禁用触发器?我的 SQL 脚本是使用 SSDT 创建项目功能从现有数据库生成的。
  • @developer 我的理解是每次表/触发器更改时,触发器都必须更改(并启用)。禁用似乎没有生效,所以 PostDeploy 是一个选项。
【解决方案2】:

如果您有一个难以管理的大型数据库并且有很多此类东西,您可能会变得棘手并创建一个过程来编写一个过程,该过程可以捕获触发器的状态并恢复它们。您可以在 PreDeploy 中运行该过程,然后在 PostDeploy 中运行生成的过程。像这样的:

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

【讨论】:

  • 顺便说一句:不确定这是否是 SSDT 本身的错误。可能是它定义了 SQL Server 行为。没有研究过这种特殊现象。
  • 感谢您的回答。启用触发器似乎是一种 SQL 服务器行为。但是,SSDT 应该禁用它以保持相同的状态 - 这似乎是一个错误。
  • 是的 - 我可以看到。 SSDT 从 SSDT 项目到同步到数据库有很多转换......但保护触发器的状态看起来不像 SSDT 感兴趣的任何事情。我认为这是一个错误,我想。跨度>
  • 我更愿意将此视为一个建议。如果您同意,您可以在 Visual Studio 开发人员社区中以Suggestion 的形式发布此内容
猜你喜欢
  • 1970-01-01
  • 2011-09-23
  • 2021-05-27
  • 1970-01-01
  • 1970-01-01
  • 2011-01-14
  • 2021-11-17
  • 1970-01-01
  • 2014-05-14
相关资源
最近更新 更多