将任何事务存储在日志 table SQL 服务器中

Store any transaction in log table SQL Server

我的 SQL 服务器数据库中有很多 table。当发生任何动作时,例如 InsertUpdateDelete,我想将数据存储在 Log table 中,如下所示:

Product table:

| ID  | Name    | Other |
| --- | ------- | ---   |
| 1   | Book    | ...   |
| 2   | Bicycle | ...   |

如果发生任何插入、更新或删除,我想要这样的东西:

Log table:

| ID  | RowId   | TableName  | Action |
| --- | ------- | ---------- | ------ |
| 1   | 1       | Product    | Insert |
| 2   | 2       | Product    | Insert |
| 3   | 15      | Category   | Update |
| 4   | 60      | Customer   | Insert |

我正在使用 Microsoft SQL Server 2008 R2 (SP2) - 10.50.4000.0 (X64) 具有高级服务的快捷版 - 我可能无法使用某些功能(参考文档)。

对于单个 table,trigger 是个好主意,而且效果很好,但是所有 table 呢?如示例所示,CategoryCustomer table 是我数据库中的其他 table。

如果你的问题是触发器的数量,你应该创建;然后创建一个作业以在创建新 table 时创建触发器。下面的代码使用特定的命名公式检查没有那种触发器的 tables。在我的示例中 tablename 加上 '_dml_audit'。无论如何你都可以改变它。

Set NOCOUNT ON

select Concat (QUOTENAME(sch.name) , '.' , QUOTENAME(tbl.name)) TableNames
into #Tables
    From sys.tables tbl
    INNER JOIN sys.schemas sch on sch.schema_id = tbl.schema_id
    LEFT JOIN sys.triggers trg on tbl.object_id = trg.parent_id and trg.name like tbl.name + '_dml_audit'
    Where trg.object_id is null

GO

exec sp_MSforeachtable 'IF ''?'' IN (Select TableNames FROM #Tables) Begin PRINT ''?'' END'

Drop Table #Tables

对于不支持#table的旧版本,使用这个:

Create Table TempTable (TableNames sysname)
GO
Insert TempTable
SELECT Concat ('[', sch.name , '].[' , tbl.name, ']') TableNames
    From sys.tables tbl
    INNER JOIN sys.schemas sch on sch.schema_id = tbl.schema_id
    LEFT JOIN sys.triggers trg on tbl.object_id = trg.parent_id and trg.name like tbl.name + '_dml_audit'
    Where trg.object_id is null

GO

exec sp_MSforeachtable 'IF ''?'' IN (Select TableNames FROM TempTable) Begin PRINT ''?'' END'
GO
Drop Table TempTable

用 PRINT 语句替换触发器定义并为其定义作业。