前言

上一篇的 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 就容易多了.

SQL Server – History Table (Audit/Archive Table)的更多相关文章

  1. SQL Server数据恢复准备之TRUNCATE TABLE理解

    SQL Server数据恢复准备之TRUNCATE TABLE理解 转自:https://blog.51cto.com/aimax/2142553 易语随风去关注0人评论6717人阅读2018-07- ...

  2. SQL Server 查看分区表(partition table)的分区范围(partition range)

    https://www.cnblogs.com/chuncn/archive/2009/02/20/1395165.html SQL Server 2005 的分区表(partition table) ...

  3. SQL Server 审计(Audit)

    审计(Audit)用于追踪和记录SQL Server实例,或者单个数据库中发生的事件(Event),审计运作的机制是通过捕获事件(Event),把事件包含的信息写入到事件日志(Event Log)或审 ...

  4. 1 SQL SERVER 实现字符串分割成table的方法

    CREATE FUNCTION [dbo].[fn_SplitStringToTable] ( @p_Input VARCHAR(MAX), @p_Delimeter CHAR() = ',' ) R ...

  5. Sql Server中的表访问方式Table Scan, Index Scan, Index Seek

    1.oracle中的表访问方式 在oracle中有表访问方式的说法,访问表中的数据主要通过三种方式进行访问: 全表扫描(full table scan),直接访问数据页,查找满足条件的数据 通过row ...

  6. 转:Sql Server中的表访问方式Table Scan, Index Scan, Index Seek

    0.参考文献 Table Scan, Index Scan, Index Seek SQL SERVER – Index Seek vs. Index Scan – Diffefence and Us ...

  7. P6 Professional Installation and Configuration Guide (Microsoft SQL Server Database) 16 R1

    P6 Professional Installation and Configuration Guide (Microsoft SQL Server Database) 16 R1       May ...

  8. SQL Server表和字段说明的增加和更新

    1. 增加字段说明 EXEC sp_addextendedproperty     'MS_Description',     'some description',     'user',      ...

  9. SQL SERVER临时表的使用

    SQL SERVER临时表的使用 drop table #Tmp   --删除临时表#Tmpcreate table #Tmp --创建临时表#Tmp(    ID   int IDENTITY (1 ...

  10. Microsoft SQL Server Version List [sqlserver 7.0-------sql server 2016]

    http://sqlserverbuilds.blogspot.jp/   What version of SQL Server do I have? This unofficial build ch ...

随机推荐

  1. Windows 10 LTSC启用Microsoft Store的方法

    新建msreg.bat文件,并编辑内容如下: ========== @echo off :: BatchGotAdmin :------------------------------------- ...

  2. Django日期字段默认值default=timezone.now

    如果你确实希望默认值是当前日期和时间,Django 提供了一个方便的函数 django.utils.timezone.now 来实现这一目的. 你可以这样调整你的模型,以使用当前日期和时间作为默认值: ...

  3. [rCore学习笔记 06]运行Lib-OS

    QEMU运行第一章代码 切换分支 git checkout ch1 detail git checkout ch1 命令是用来切换到名为 ch1 的分支或者恢复工作目录中的文件到 ch1 提交的状态 ...

  4. mysql数据库无法录入汉字问题

    1.插入数据出现错误 show full columns from 表名;//查看数据表列编码 2. alter table 表名 change 列名 列名 varchar(自己设置) charact ...

  5. 银河麒麟V10高级服务器编译安装pg13.4

    安装postgres依赖 yum install -y openssl openssl-devel pam pam-devel libxml2 libxml2-devel libxslt libxsl ...

  6. SptingBoot同时接收文件和对象数据(接收表单数据)

    emmm...虽然很简单,而且网上全是教程,但是自己做个笔记映像才会更深刻,还请各位前辈多多指教: @RequestMapping(value = "/eventPush", me ...

  7. 【DataBase】MySQL 06 条件查询 & 排序查询

    视频参考自:P28 - P42 https://www.bilibili.com/video/BV1xW411u7ax 条件查询概述 # 进阶2 条件查询 -- 语法:SELECT 查询列表 FROM ...

  8. 【Java】自制查找工具

    需求:查找后台代码中写的SQL是否包含拆分表,如果存在,则返回那些表名 Context.txt 粘贴我们找到的DAO层代码,因为所有方法封装的SQL都在DAO层里[就理解为筛查的字符串] Dictio ...

  9. 【Layui】05 选项卡 Tabs

    文档位置: https://www.layui.com/doc/element/tab.html 案例演示: <div class="layui-tab"> <u ...

  10. 为什么我们需要不断的开发不同的机器学习模型 —— Do we Need Hundreds of Classifiers to Solve Real World Classification Problems?

    引用: 作者:xyzh https://www.zhihu.com/question/26726794/answer/151282052 写给懒得看的人: 没有最好的分类器,只有最合适的分类器. 随机 ...