好的,看来我有一个潜在的解决方案:临时表
临时表在 Azure 中工作,并在发生变化时在历史表中记录一个新行:-
CREATE TABLE dbo.LMSTemporalTest
(
[EmployeeID] INT NOT NULL PRIMARY KEY CLUSTERED
, [Name] NVARCHAR(100) NOT NULL
, [Position] NVARCHAR(100) NOT NULL
, [Department] NVARCHAR(100) NOT NULL
, [Address] NVARCHAR(1024) NOT NULL
, [AnnualSalary] DECIMAL (10,2) NOT NULL
, [UpdatedBy] UniqueIdentifier NOT NULL
, [UpdatedDate] DateTime NOT NULL
, [ValidFrom] DateTime2 (2) GENERATED ALWAYS AS ROW START HIDDEN
, [ValidTo] DateTime2 (2) GENERATED ALWAYS AS ROW END HIDDEN
, PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.LMSTemporalTestHistory));
GO
然后我可以在表中插入一条记录...
INSERT INTO LMSTemporalTest(EmployeeID,Name,Position,Department,Address,AnnualSalary, UpdatedBy, UpdatedDate)
VALUES(1, 'Bob', 'Builder', 'Fixers','Oops I forgot', 1, '0D7F5584-C79B-4044-87BD-034A770C4985', GetDate())
GO
更新行...
UPDATE LMSTemporalTest SET
Address = 'Sunflower Valley, Bobsville',
UpdatedBy = '2C62290B-61A9-4B75-AACF-02B7A5EBFB80',
UpdatedDate = GetDate()
WHERE EmployeeID = 1
GO
再次更新该行...
UPDATE LMSTemporalTest SET
AnnualSalary = 420.69,
UpdatedBy = '47F25135-35ED-4855-8050-046CD73E5A7D',
UpdatedDate = GetDate()WHERE EmployeeID = 1
GO
然后查看结果:-
SELECT * FROM LMSTemporalTest
GO
EmployeeID Name Position Department Address AnnualSalary UpdatedBy UpdatedDate
1 Bob Builder Fixers Sunflower Valley, Bobsville 420.69 47F25135-35ED-4855-8050-046CD73E5A7D 2019-07-01 16:20:00.230
注意:因为我将它们设置为隐藏,所以 Valid From 和 Valid To 不显示
检查日期/时间范围的更改:-
SELECT * FROM LMSTemporalTest
FOR SYSTEM_TIME BETWEEN '2019-Jul-01 14:00' AND '2019-Jul-01 17:10'
WHERE EmployeeID = 1
ORDER BY ValidFrom;
GO
EmployeeID Name Position Department Address AnnualSalary UpdatedBy UpdatedDate
1 Bob Builder Fixers Oops I forgot 1.00 0D7F5584-C79B-4044-87BD-034A770C4985 2019-07-01 16:20:00.163
1 Bob Builder Fixers Sunflower Valley, Bobsville 1.00 2C62290B-61A9-4B75-AACF-02B7A5EBFB80 2019-07-01 16:20:00.197
1 Bob Builder Fixers Sunflower Valley, Bobsville 420.69 47F25135-35ED-4855-8050-046CD73E5A7D 2019-07-01 16:20:00.230
我什至可以查看历史记录表
SELECT * FROM LMSTemporalTestHistory
GO
EmployeeID Name Position Department Address AnnualSalary UpdatedBy UpdatedDate ValidFrom ValidTo
1 Bob Builder Fixers Oops I forgot 1.00 0D7F5584-C79B-4044-87BD-034A770C4985 2019-07-01 16:20:00.163 2019-07-01 16:20:00.16 2019-07-01 16:20:00.19
1 Bob Builder Fixers Sunflower Valley, Bobsville 1.00 2C62290B-61A9-4B75-AACF-02B7A5EBFB80 2019-07-01 16:20:00.197 2019-07-01 16:20:00.19 2019-07-01 16:20:00.22
注意:当前行不显示,因为它仍然有效
我们所有的重要表都已经有 CreatedBy、CreatedDate、UpdatedBy 和 UpdatedDate,所以我可以将它们用于 UserID 日志记录。没有将程序和版本作为标准处理的明显方法,但我总是可以添加另一个隐藏字段并使用触发器来设置它。
编辑:实际测试过
第一个障碍是:您是否真的可以将现有表更改为临时表,答案是:可以!
ALTER TABLE Clients ADD
[ValidFrom] DateTime2 (2) GENERATED ALWAYS AS ROW START HIDDEN NOT NULL DEFAULT '1753-01-01 00:00:00.000',
[ValidTo] DateTime2 (2) GENERATED ALWAYS AS ROW END HIDDEN NOT NULL DEFAULT '9999-12-31 23:59:59.997',
PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
GO
ALTER TABLE Clients SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.ClientsHistory))
GO
上面的重要一点是 ValidFrom 和 ValidTo 字段的默认值。它仅在 ValidTo 是 DateTime2 可以达到的最大值时才有效,因此是 '9999-12-31 23:59:59.997'。 ValidFrom 似乎无关紧要,所以我将其设置为最低限度以涵盖所有内容。
好的,所以我已经转换了一个表,但它现在有两个非 Azure 表没有的额外字段,理论上是隐藏的,但是我们的软件会抱怨它们吗?
好像没有。启动软件,在Clients表中编辑一条记录并保存,软件完全没有报错。
检查了 Clients 和 ClientsHistory 表:-
SELECT * FROM Clients
FOR SYSTEM_TIME BETWEEN '1753-01-01 00:00:00.000' AND '9999-12-31 23:59:59.997'
WHERE sCAccountNo = '0001064'
ORDER BY ValidFrom
显示两条记录,原始记录和已编辑记录,并且现有的 UpdatedUser 和 UpdatedDate 字段显示正确,因此我知道谁进行了更改以及何时进行了更改。
SELECT * FROM ClientsHistory
显示原始记录,ValidTo 设置为更改日期,
一切似乎都很好,现在我只需要检查它是否仍然只返回查询中的当前记录和我们的软件:-
SELECT * FROM Clients
WHERE sCAccountNo = '0001064'
只返回一条记录,不显示 HIDDEN 字段 ValidFrom 和 ValidTo。
在我们的软件中搜索了客户端 0001064,它再次只返回了一条记录,并没有抱怨两个额外的字段。
仍然需要设置一些触发器并添加另一个 HIDDEN 字段来记录连接字符串中的程序和版本,但看起来 Temporal Tables 给了我一个可行的审计选项。
到目前为止唯一的缺点是它为每组更改创建一个完整的记录行,这意味着您必须将其与其他记录进行比较以找出更改的内容,但我可以写一些东西来简化这一点。