背景
这是一个与我正在使用的相似的示例:
CREATE TABLE sandboxTesting.TemporalTest (
GroupNumber VARCHAR(25) NOT NULL,
StartEffectiveWhen DATE NOT NULL,
EndEffectiveWhen DATE NULL,
ModifiedWhen DATETIME NULL,
IsReady BIT NOT NULL DEFAULT 0,
RowValidFrom DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL,
RowValidTo DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME (RowValidFrom, RowValidTo),
CONSTRAINT PK_TemporalTest PRIMARY KEY CLUSTERED
(
GroupNumber, StartEffectiveWhen
)
) WITH (SYSTEM_VERSIONING=ON (HISTORY_TABLE=sandboxTesting.TemporalTestHistory))
GO
CREATE TRIGGER sandboxTesting.OnModify ON sandboxTesting.TemporalTest AFTER UPDATE AS
BEGIN
UPDATE temporalTst
SET temporalTst.IsReady = 0,
temporalTst.ModifiedWhen = GETDATE()
FROM sandboxTesting.TemporalTest temporalTst
JOIN deleted del
ON del.GroupNumber = temporalTst.GroupNumber
AND del.StartEffectiveWhen = temporalTst.StartEffectiveWhen
WHERE -- All business columns go here with OR statements in between them.
-- The idea is that if anything changes except the IsReady flag, then we
-- set the IsReady back to false. (IsReady has to be set by itself)
del.EndEffectiveWhen <> temporalTst.EndEffectiveWhen
OR (del.EndEffectiveWhen IS NULL AND temporalTst.EndEffectiveWhen IS NOT NULL)
OR (del.EndEffectiveWhen IS NOT NULL AND temporalTst.EndEffectiveWhen IS NULL)
END
GO
-- Insert new test
INSERT INTO [sandboxTesting].[TemporalTest] ([GroupNumber], [StartEffectiveWhen], [EndEffectiveWhen], [ModifiedWhen])
VALUES ('12345', '2024-01-1', NULL, NULL)
GO
-- Set is as ready
UPDATE sandboxTesting.TemporalTest
SET IsReady = 1
WHERE GroupNumber = '12345' AND StartEffectiveWhen = '2024-01-1'
GO
-- Change the End date
UPDATE sandboxTesting.TemporalTest
SET EndEffectiveWhen = '2024-09-02'
WHERE GroupNumber = '12345' AND StartEffectiveWhen = '2024-01-1'
-- Set the new end date as ready for billing.
UPDATE sandboxTesting.TemporalTest
SET IsReady = 1
WHERE GroupNumber = '12345' AND StartEffectiveWhen = '2024-01-1'
GO
-- Select the Data
SELECT * FROM sandboxTesting.TemporalTest for SYSTEM_TIME ALL
ORDER BY GroupNumber, StartEffectiveWhen desc, RowValidFrom DESC, RowValidTo DESC, ModifiedWhen desc
-- Select the Raw Data (for comparison)
SELECT * FROM sandboxTesting.TemporalTest
UNION ALL
SELECT * FROM sandboxTesting.TemporalTestHistory
ORDER BY GroupNumber, StartEffectiveWhen desc, RowValidFrom DESC, RowValidTo DESC, ModifiedWhen desc
当我运行它时,这是第一个结果:
群组号码 | 开始生效时间 | 生效日期 | 修改时间 | 已就绪 | 行有效地址 | RowValidTo |
---|---|---|---|---|---|---|
12345 | 2024-01-01 | 2024-09-02 | 2024-08-29 17:15:28.587 | 1 | 2024-08-29 23:15:28.5764223 | 9999-12-31 23:59:59.9999999 |
12345 | 2024-01-01 | 无效的 | 无效的 | 1 | 2024-08-29 23:15:28.5295658 | 2024-08-29 23:15:28.5764223 |
12345 | 2024-01-01 | 无效的 | 无效的 | 0 | 2024-08-29 23:15:28.4826980 | 2024-08-29 23:15:28.5295658 |
第二组输出如下:
群组号码 | 开始生效时间 | 生效日期 | 修改时间 | 已就绪 | 行有效地址 | RowValidTo |
---|---|---|---|---|---|---|
12345 | 2024-01-01 | 2024-09-02 | 2024-08-29 17:15:28.587 | 1 | 2024-08-29 23:15:28.5764223 | 9999-12-31 23:59:59.9999999 |
12345 | 2024-01-01 | 2024-09-02 | 2024-08-29 17:15:28.587 | 0 | 2024-08-29 23:15:28.5764223 | 2024-08-29 23:15:28.5764223 |
12345 | 2024-01-01 | 2024-09-02 | 无效的 | 1 | 2024-08-29 23:15:28.5764223 | 2024-08-29 23:15:28.5764223 |
12345 | 2024-01-01 | 无效的 | 无效的 | 1 | 2024-08-29 23:15:28.5295658 | 2024-08-29 23:15:28.5764223 |
12345 | 2024-01-01 | 无效的 | 无效的 | 0 | 2024-08-29 23:15:28.4826980 | 2024-08-29 23:15:28.5295658 |
这是不同的,因为第一个查询结果使用了for SYSTEM_TIME ALL
子句,而第二个查询结果只是查询原始数据。
不同之处在于,在第一个数据集中,第二个数据集的第二行和第三行已被过滤掉。它们被删除是因为第二行和第三行的开始日期和结束日期相同。(基本上说这些行从未真正生效。)
问题
我需要知道的是,对于通过触发器更新的数据,我是否可以依赖这个“零时间差” AFTER
?(如果不是这种情况,我需要编写一些查询,这些查询将会失败。)
我的意思是:如果我的服务器被数千个查询所困扰,这些查询都进行着大量的 IO 和计算,那么第二个数据集的第二行和第三行的RowValidFrom
和RowValidTo
值的差是否仍然为 0?
换句话说,这些值是否因为事务逻辑而相同?还是因为我的服务器速度很快并且目前没有任何压力,所以它们相同?