【问题标题】:how to batch edit triggers?如何批量编辑触发器?
【发布时间】:2012-06-24 22:03:35
【问题描述】:

我有许多触发器,我想使用通配符构建一个表列表,然后通过向触发器添加一些列名来更新它们上的现有触发器。每个触发器中的列名都相同,但我不清楚如何构建表列表或如何在单个 alter trigger 语句中循环列表。我想我必须使用光标....

【问题讨论】:

    标签: sql sql-server sql-server-2008 tsql


    【解决方案1】:

    没有魔杖可以说“将this code 添加到所有触发器”(或任何其他对象类型,就此而言)。

    对于许多对象类型,对于批量编辑,您可以使用对象资源管理器详细信息以及该视图中的排序和/或过滤快速生成多个对象的脚本。例如,如果您在对象资源管理器中突出显示“存储过程”,它们都会在对象资源管理器详细信息中列出,您可以选择多个对象,右键单击,并将存储过程编写为 > 创建到 >

    由于触发器嵌套在表下,因此没有方便的方法来执行此操作(触发器也不是您可以在右键单击数据库并选择任务 > 生成脚本时选择的实体类型)。但是您可以很容易地从元数据中提取脚本(运行此脚本时,您需要在 Management Studio 中使用 Results to Text):

    SET NOCOUNT ON;
    
    SELECT OBJECT_DEFINITION([object_id]) 
      + CHAR(13) + CHAR(10) + 'GO' + CHAR(13) + CHAR(10)
      FROM sys.triggers
      WHERE type = 'TR';
    

    您可以获取输出,将其复制并粘贴到顶部窗格中,然后将新代码添加到每个触发器后,您将需要做更多的工作,例如搜索/替换 'CREATE TRIGGER''ALTER TRIGGER'。您也可以将其作为查询的一部分进行,但它依赖于具有一致编码约定的创建者。由于某些触发器可能看起来像这样......

    create          trigger
    

    ...你可能需要用手按摩一些。

    如果您只对某组表感兴趣,也可以过滤上面的查询。例如,要仅更改与以 Sales 开头的表关联的触发器,您可以说:

    AND OBJECT_NAME(parent_id) LIKE N'Sales%';
    

    或仅适用于 Person 架构中的表:

    AND OBJECT_SCHEMA_NAME(parent_id) = N'Person';
    

    无论如何,一旦您对脚本进行了所有必要的调整,您就可以运行它。比扩展每个表并为这些触发器生成脚本要容易得多。

    【讨论】:

    • Aaron 我喜欢你的建议,并设法在 notepad++ 中一起破解了一些东西,我可以在其中查找和替换并放入需要替换的代码块。 select from sys.triggers 确实有帮助,正如你所说,我可以添加通配符来处理“一致的编码约定”。但是,我从之前的帖子中听取了您的建议,并编写了一个 SP,以便我自己(和其他 DB 开发人员)将来也许可以自动化一些批量编辑。
    【解决方案2】:

    除了 Aarons 的建议(它在一系列具有不一致的对象命名约定的复杂触发器上效果很好)之外,我还尝试编造一些东西,这样我就可以记住我在 3 个月内做了什么。享受。创建或更改 SP,然后在没有参数的情况下执行。

    CREATE PROCEDURE SP_ALTER_CONTOUR_TRIGS
    --sp to bulk edit many triggers at once
    --NO ERROR HANDLING!
    AS 
        DECLARE
            @sql VARCHAR(500),
            @tableName VARCHAR(128),
            @triggerName VARCHAR(128),
            @tableSchema VARCHAR(128)
    
    
        DECLARE triggerCursor CURSOR
            FOR
        SELECT
            so_tr.name AS TriggerName,
            so_tbl.name AS TableName,
            t.TABLE_SCHEMA AS TableSchema
        FROM
            sysobjects so_tr
        INNER JOIN sysobjects so_tbl ON so_tr.parent_obj = so_tbl.id
        INNER JOIN INFORMATION_SCHEMA.TABLES t 
        ON 
            t.TABLE_NAME = so_tbl.name
       WHERE
       --here's where you want to build filters to make sure you're 
       --targeting the trigs you want edited
       --BE CAREFUL!
       --test the select statement first against sysobjects
       --to see that it returns what you expect
            so_tr.type = 'TR'
            and so_tbl.name like '%contours'
            and so_tr.name like'%location_id'
    
        ORDER BY
            so_tbl.name ASC,
            so_tr.name ASC
    
        OPEN triggerCursor
    
        FETCH NEXT FROM triggerCursor 
        INTO @triggerName, @tableName, @tableSchema
    
        WHILE ( @@FETCH_STATUS = 0 )
            BEGIN
    --insert alter statement below
    --watch out for cr returns and open and close qoutes!
    --seems to act finicky if you don't use schema-bound naming convention
    SET @sql = '
    ALTER TRIGGER ['+ @tableSchema +'].['
    + @triggerName + '] ON ['+ @tableSchema +'].['
    + @tableName + ']
    INSTEAD OF INSERT
    AS
    BEGIN
    SET NOCOUNT ON; 
    INSERT ['+ @tableSchema +'].['+ @tableName + '] 
    (OBJECTID, Contour, Type, Shape, RuleID, Override)
    SELECT 
    a.OBJECTID, a.Contour, a.Type, a.Shape, a.RuleID, a.Override
    FROM 
    (SELECT 
    OBJECTID, Contour, Type, Shape, RuleID, Override
    FROM inserted)
    AS a
    END
    '
    
    
                PRINT 'Executing Statement - '+ @sql
                EXECUTE ( @sql )
                FETCH NEXT FROM triggerCursor 
                INTO @triggerName, @tableName,  @tableSchema
            END
    
        CLOSE triggerCursor
        DEALLOCATE triggerCursor
    

    【讨论】:

      猜你喜欢
      • 2020-05-19
      • 1970-01-01
      • 2013-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-17
      • 1970-01-01
      • 2011-12-06
      相关资源
      最近更新 更多