2012-06-23 55 views
0

我有很多的觸發器,我想針對通過加入一些列名觸發建立使用通配符表的列表,然後更新他們現有的觸發器。列名在每個觸發器中都是相同的,但我不清楚如何構建表的列表或如何在單個更改觸發器語句中遍歷列表。我假設我將不得不使用遊標....如何批量編輯觸發器?

回答

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'; 

無論如何,一旦你已經做了一切必要的調整,腳本,你可以運行它。比擴展每個表格併爲這些觸發器生成腳本要容易得多。

+0

Aaron我喜歡你的建議,並設法在記事本++中一起破解一些東西,我可以在其中找到並替換代碼塊,並在需要替換的代碼塊中刪除。從sys.triggers中選擇真的幫了我很大的忙,我可以添加通配符來處理,就像你說的'一致的編碼約定'。但是,我從早期的文章中接受了您的建議,並編寫了一份SP,以便我(和其他DB開發人員)可以在將來自動進行一些批量編輯。 – tpcolson

0

除了阿倫斯建議,該建議與不一致的對象命名約定一堆複雜的觸發器的偉大的工作,我則嘗試煮的東西,所以我會記得我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