且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-01-31 13:30:45

不可能触发一个触发器当任何表被更新时。

It is not possible to have a trigger that fires when any table is updated.

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

You could generate the SQL Required dynamically, the following:

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列沿行:

Generates SQL for each table with a LastUpdate column along the lines of:

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

每个表都具有主键才能从插入表回到要更新的表。

The relies on each table having a primary key to get the join from the inserted table back to the table being updated.

您可以复制并粘贴结果并执行(我会推荐这种方式,这样您至少可以检查生成的SQL,或将其构建到游标中并使用 sp_executesql 执行它。我建议使用前者,即,使用它来保存

You can either copy and paste the results and execute them (I would recommend this way so you can at least check the SQL Generated, or build it into a cursor and execute it using sp_executesql. I would recommend the former, i.e. use this to save a bit of time, but still check each trigger before actually creating it.

我个人认为最后修改的列是一个有缺陷的概念,在我看来,它总是喜欢存储烦人的少量信息,如果您确实关心数据更改,则可以使用审计表对其进行正确跟踪:首先,知道什么时候更改了什么,但是从何而来,或者是谁更改了,比根本不知道更令人讨厌,其次,它覆盖了所有内容。以前的更改,是什么使最新的更改比所有更改都重要以前已经过去了。

I personally think last modified columns are a flawed concept, it always feels to me like storing annoyingly little information, if you really care about data changes then track them properly with an audit table. Firstly, knowing when something was changed, but what it was changed from, or who changed it is probably more annoying than not knowing at all, secondly it overwrites all previous changes, what makes the latest change more important than all those that have gone before.