如何在SQL Server数据库中为所有表创建触发器。

6

我在数据库的所有表中都有一个名为LastUpdate的列,并且我想要在插入或更新时自动设置LastUpdate = getdate()

我可以使用触发器来实现,但是我发现为每个表编写数百个触发器非常困难。 - 如何动态地创建影响所有表的触发器? - 如何为每个表动态创建触发器?

1个回答

12

不能有一个触发器可以在任何表更新时触发。

您可以动态生成所需的SQL,如下所示:

SELECT  N'
            CREATE TRIGGER trg_' + t.Name + '_Update ON ' + ObjectName + '
            AFTER UPDATE 
            AS 
            BEGIN
                UPDATE  t
                SET LastUpdate = GETDATE()
                FROM ' + o.ObjectName + ' AS t
                        INNER JOIN inserted AS i
                            ON ' + 
            STUFF((SELECT ' AND t.' + QUOTENAME(c.Name) + ' = i.' + QUOTENAME(c.Name)
                    FROM    sys.index_columns AS ic
                            INNER JOIN sys.columns AS c
                                ON c.object_id = ic.object_id
                                AND c.column_id = ic.column_id
                    WHERE   ic.object_id = t.object_id
                    AND     ic.index_id = ix.index_id
                    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 4, '') + ';
            END;
            GO'
FROM    sys.tables AS t
        INNER JOIN sys.indexes AS ix
            ON ix.object_id = t.object_id
            AND ix.is_primary_key = 1
        CROSS APPLY (SELECT QUOTENAME(OBJECT_SCHEMA_NAME(t.object_id)) + '.' + QUOTENAME(t.name)) o (ObjectName)
WHERE   EXISTS 
        (   SELECT  1 
            FROM    sys.columns AS c 
            WHERE   c.Name = 'LastUpdate' 
            AND     c.object_id = t.object_id
        );

为每个带有LastUpdate列的表生成SQL,大致如下:

CREATE TRIGGER trg_TableName_Update ON [dbo].[TableName]
AFTER UPDATE 
AS 
BEGIN
    UPDATE  t
    SET     LastUpdate = GETDATE()
    FROM    [dbo].[TableName] AS t
            INNER JOIN inserted AS i
                ON  t.[PrimaryKey] = i.[PrimaryKey];
END;
GO

这个触发器依赖于每个表都有一个主键,以便从inserted表中获取连接到正在更新的表。

您可以复制并粘贴结果并执行它们(我建议使用这种方式,这样您至少可以检查生成的 SQL),或者将其构建成游标并使用sp_executesql执行它。我建议前者,即使用它来节省一些时间,但在实际创建之前仍要检查每个触发器。

我个人认为最后修改列是一个有缺陷的概念,它总让我感觉存储了很少的信息,如果您真的关心数据更改,则应该使用审核表(或临时表或使用Change Tracking)正确跟踪它们。首先,知道什么时候更改了某些内容,但不知道更改前的内容或者是谁更改的,可能比根本不知道更烦人。其次,它会覆盖所有先前的更改,这使得最新的更改比之前的更改更重要。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接