【发布时间】:2012-06-24 22:03:35
【问题描述】:
我有许多触发器,我想使用通配符构建一个表列表,然后通过向触发器添加一些列名来更新它们上的现有触发器。每个触发器中的列名都相同,但我不清楚如何构建表列表或如何在单个 alter trigger 语句中循环列表。我想我必须使用光标....
【问题讨论】:
标签: sql sql-server sql-server-2008 tsql
我有许多触发器,我想使用通配符构建一个表列表,然后通过向触发器添加一些列名来更新它们上的现有触发器。每个触发器中的列名都相同,但我不清楚如何构建表列表或如何在单个 alter trigger 语句中循环列表。我想我必须使用光标....
【问题讨论】:
标签: sql sql-server sql-server-2008 tsql
没有魔杖可以说“将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';
无论如何,一旦您对脚本进行了所有必要的调整,您就可以运行它。比扩展每个表并为这些触发器生成脚本要容易得多。
【讨论】:
除了 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
【讨论】: