如何在时态表中排除指定列不存入对应的历史表?
实现时态表排除指定字段不记录历史的方法
针对你希望Data2字段变更不存入SampleHistory历史表的需求,有两种可靠的实现方式:
方法一:拆分表结构(推荐)
将需要审计的字段和无需审计的字段分离为两个表,仅对含审计字段的表启用系统版本控制,从根源上避免非审计字段生成历史记录:
- 创建带系统版本控制的主表(仅包含需要审计的字段):
CREATE TABLE dbo.Sample ( SampleId int identity(1,1) PRIMARY KEY CLUSTERED , SampleDate date NOT NULL , Data1 varchar(50) , SysStartTime datetime2 GENERATED ALWAYS AS ROW START , SysEndTime datetime2 GENERATED ALWAYS AS ROW END , PERIOD FOR SYSTEM_TIME (SysStartTime, SysEndTime) ) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.SampleHistory));
- 创建独立表存储无需审计的
Data2字段:
CREATE TABLE dbo.SampleNonAudit ( SampleId int PRIMARY KEY FOREIGN KEY REFERENCES dbo.Sample(SampleId) , Data2 varchar(50) );
后续SampleNonAudit表的任何变更都不会生成历史记录,仅Sample表的字段变更会被SampleHistory追踪,既节省存储空间又满足审计需求。
方法二:自定义触发器替代系统版本控制(按需使用)
如果无法拆分表结构,可关闭原生系统版本控制,改用触发器手动记录指定字段的变更:
- 先关闭原时态表的系统版本控制并删除自动生成的历史表:
ALTER TABLE dbo.Sample SET (SYSTEM_VERSIONING = OFF); DROP TABLE dbo.SampleHistory;
- 手动创建仅包含审计字段的历史表:
CREATE TABLE dbo.SampleHistory ( SampleId int , SampleDate date NOT NULL , Data1 varchar(50) , SysStartTime datetime2 , SysEndTime datetime2 , PRIMARY KEY (SampleId, SysStartTime) );
- 创建触发器,仅在审计字段变更时写入历史记录:
-- INSERT触发器:记录新数据的初始状态 CREATE TRIGGER trg_Sample_Insert ON dbo.Sample AFTER INSERT AS BEGIN INSERT INTO dbo.SampleHistory (SampleId, SampleDate, Data1, SysStartTime, SysEndTime) SELECT SampleId, SampleDate, Data1, SYSUTCDATETIME(), '9999-12-31 23:59:59.9999999' FROM inserted; END; -- UPDATE触发器:仅当审计字段变更时更新历史 CREATE TRIGGER trg_Sample_Update ON dbo.Sample AFTER UPDATE AS BEGIN -- 仅在SampleDate或Data1变更时执行历史记录逻辑 IF UPDATE(SampleDate) OR UPDATE(Data1) BEGIN -- 标记原记录的结束时间 UPDATE h SET h.SysEndTime = SYSUTCDATETIME() FROM dbo.SampleHistory h JOIN deleted d ON h.SampleId = d.SampleId WHERE h.SysEndTime = '9999-12-31 23:59:59.9999999'; -- 插入新记录的当前状态 INSERT INTO dbo.SampleHistory (SampleId, SampleDate, Data1, SysStartTime, SysEndTime) SELECT SampleId, SampleDate, Data1, SYSUTCDATETIME(), '9999-12-31 23:59:59.9999999' FROM inserted; END; END;
注意:SQL Server原生系统版本时态表的设计是追踪全字段变更,没有直接排除指定字段的配置项,因此上述两种方法是当前可行的替代方案。
内容的提问来源于stack exchange,提问作者sorosh_sabz
相关产品推荐
相关产品推荐

