zoukankan      html  css  js  c++  java
  • SQL Server – History Table (Audit/Archive Table)

    前言

    上一篇的 Soft Delete 后, 我们继续来看看 History Table (Audit/Archive Table).

    Archive Table 市场上有了这样叫, 但我觉得它比较杂, 因为它既保存了 History, 也多少记入 operation 和时间, 所以带有一点 Audit 的味道.

    我们姑且叫它 HIstory Table 就好呗.

    上回说到我们的需求就是不希望任何数据被删除, 找不回来.

    除了 Soft Delete, Temporal Table 能完成这个需求, 还有就是 History Table.

    也就就是自己做一个 table 然后把所有 delete/update 移除的数据放以 json 的方式存进去. (和 temporal 差不多, 只是 temporal 是每一个表都一个 history table, 然后它不是 json 而是完整的表结构) 

    这个方案的优点就是没有 Temporal 那么重, 又比 Soft Delete 轻.

    Step 1: Create History Table

    大概长这样

    Step 2: Trigger After Delete

    GO
    CREATE OR ALTER TRIGGER [TR_Country_AfterDelete_ForAuditData] ON [Country]
    AFTER DELETE 
    AS
        IF (ROWCOUNT_BIG() = 0) RETURN;
        SET NOCOUNT ON;
    
        DECLARE @i int = 0, @count int;
        SELECT @count = COUNT(*) FROM deleted;
        DECLARE @dateCreated datetimeoffset(3) = CAST(SYSDATETIMEOFFSET() AT TIME ZONE 'Singapore Standard Time' AS datetimeoffset(3));
    
        WHILE(@i < @count)
        BEGIN
            INSERT INTO AuditDataLog (TableName, Operation, DeletedDataJson, InsertedDataJson, DateCreated) 
            VALUES (
                'Country', 
                'Delete', 
                (SELECT * FROM (SELECT * FROM deleted ORDER BY CountryId OFFSET @i ROWS FETCH NEXT 1 ROWS ONLY) Temp FOR JSON AUTO, INCLUDE_NULL_VALUES, WITHOUT_ARRAY_WRAPPER), 
                NULL, 
                @dateCreated
            );
            SET @i += 1;
        END 
    GO

    要记得哦, deleted 是一个表, 里面会有很多 deleted rows 的. 这里把 deleted row 一条一条 insert 是为了以后方便 filter 查看. 但是会让性能慢的哦.

    Step 3: Trigger After Update

    和上面差不多, 只是多了一句 for inserted 而已.

    GO
    CREATE OR ALTER TRIGGER [TR_Country_AfterDelete_ForAuditData] ON [Country]
    AFTER UPDATE 
    AS
        IF (ROWCOUNT_BIG() = 0) RETURN;
        SET NOCOUNT ON;
    
        DECLARE @i int = 0, @count int;
        SELECT @count = COUNT(*) FROM deleted;
        DECLARE @dateCreated datetimeoffset(3) = CAST(SYSDATETIMEOFFSET() AT TIME ZONE 'Singapore Standard Time' AS datetimeoffset(3));
    
        WHILE(@i < @count)
        BEGIN
            INSERT INTO AuditDataLog (TableName, Operation, DeletedDataJson, InsertedDataJson, DateCreated) 
            VALUES (
                'Country', 
                'Update', 
                (SELECT * FROM (SELECT * FROM deleted ORDER BY CountryId OFFSET @i ROWS FETCH NEXT 1 ROWS ONLY) Temp FOR JSON AUTO, INCLUDE_NULL_VALUES, WITHOUT_ARRAY_WRAPPER), 
                (SELECT * FROM (SELECT * FROM inserted ORDER BY CountryId OFFSET @i ROWS FETCH NEXT 1 ROWS ONLY) Temp FOR JSON AUTO, INCLUDE_NULL_VALUES, WITHOUT_ARRAY_WRAPPER), 
                @dateCreated
            );
            SET @i += 1;
        END 
    GO

    题外话:

    本来想把这个表叫 AuditDataLog 的, 但由于 deleted 没有办法记入 DeletedBy (除非搞一些 stored procedure)

    所以还是把它定位为 History Table 就好了. 如果想知道是谁 delete 了, 那么这里获取到时间后, 在去查 Audit Api Log, 有了时间范围, 要找出谁 performance 了相关 action 就容易多了.

  • 相关阅读:
    solr 最佳实践
    DNS 域名解析过程
    mac 下 virtualbox 配置全网通
    搜索引擎使用技巧
    三叉搜索树
    双数组trie树的基本构造及简单优化
    基于回归-马尔科夫模型的客运量预测
    solr 常用命令
    PHP yield 分析,以及协程的实现,超详细版(上)
    C语言,简单计算器【上】
  • 原文地址:https://www.cnblogs.com/keatkeat/p/15595810.html
Copyright © 2011-2022 走看看