我试图告诉历史表,某个记录在与其原始 ValidFrom
和 ValidTo
值不同的时间范围内“相关”,如下所示:
ALTER TABLE dbo.statusForStudents SET (SYSTEM_VERSIONING = OFF);
update history.statusForStudents set validfrom='2020-10-25 11:12:07.40',ValidTo='2020-10-26 12:48:31.19' where ValidFrom='2020-12-03 11:12:07.40' and id=1066255
ALTER TABLE statusForStudents
SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE =history.statusForStudents));
即:
我关掉 TT,
更新相关记录,
然后再次打开 TT。
这确实有效, 但是,当我更新当前值时,在 TT 再次打开后:
update statusForStudents set PrimaryStatusID=1 where id=1066255
由于某种原因,TT 机制似乎在上一个 ValidTo
时间和下一个 ValidFrom
时间之间“跳过”了几秒钟:
我从未在历史表格中看到过这样的差距..
这是一个错误吗?
有办法克服吗?
最佳答案
说明
如果您更新的历史记录行在 2020-12-03 11:12:07.40
到 2020-12-03 12:12.67
期间有效,则此操作有意义。开始时间与您的历史更新语句相符...
复制
创建时态表
create table StatusForStudents
(
Id bigint NOT NULL PRIMARY KEY CLUSTERED
, PrimaryStatusId int
, SysStartTime DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL
, SysEndTime DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL
, PERIOD FOR SYSTEM_TIME (SysStartTime,SysEndTime)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.StatusForStudentsHistory));
创建一些历史记录
-- status = 1 for 1 sec
insert into StatusForStudents (Id, PrimaryStatusId) values (1066255, 1);
WAITFOR DELAY '00:00:01';
-- status = 100 for 2 sec
update StatusForStudents set PrimaryStatusId = 100 where Id = 1066255;
WAITFOR DELAY '00:00:02';
-- status = 3 as current status
update StatusForStudents set PrimaryStatusId = 3 where Id = 1066255;
这给了我:
-- StatusForStudents
Id PrimaryStatusId SysStartTime SysEndTime
------- --------------- --------------------------- ---------------------------
1066255 3 2020-12-06 19:55:40.9777475 9999-12-31 23:59:59.9999999
--StatusForStudentsHistory
Id PrimaryStatusId SysStartTime SysEndTime
------- --------------- --------------------------- ---------------------------
1066255 1 2020-12-06 19:55:37.9464833 2020-12-06 19:55:38.9621205
1066255 100 2020-12-06 19:55:38.9621205 2020-12-06 19:55:40.9777475
扰乱历史
ALTER TABLE dbo.statusForStudents SET (SYSTEM_VERSIONING = OFF);
-- get start date for history row with status = 100
declare @Reference datetime2;
select @Reference = h.SysStartTime
from StatusForStudentsHistory h
where h.Id = 1066255
and h.PrimaryStatusId = 100;
-- update history row for status = 100 through start date filter
update statusForStudentsHistory
set SysStartTime = '2020-10-25 11:12:07.40',
SysEndtime = '2020-10-26 12:48:31.19'
where Id = 1066255
and SysStartTime = @Reference;
ALTER TABLE statusForStudents SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.StatusForStudentsHistory));
新更新
-- status = 1 as current status
update StatusForStudents set PrimaryStatusID = 1 where Id = 1066255;
这给了我:
-- StatusForStudents
Id PrimaryStatusId SysStartTime SysEndTime
------- --------------- --------------------------- ---------------------------
1066255 1 2020-12-06 19:55:40.9933283 9999-12-31 23:59:59.9999999
--StatusForStudentsHistory
Id PrimaryStatusId SysStartTime SysEndTime
------- --------------- --------------------------- ---------------------------
1066255 100 2020-10-25 11:12:07.4000000 2020-10-26 12:48:31.1900000
1066255 1 2020-12-06 19:55:37.9464833 2020-12-06 19:55:38.9621205
1066255 3 2020-12-06 19:55:40.9777475 2020-12-06 19:55:40.9933283
现在历史表中状态为 1 和 3 的行之间似乎有 2 秒的间隙。然而,这正是更新的持续时间为 2 秒(状态 = 100)的行。在本例中,“间隙”是由历史记录更新引入的。
结论
手动更新历史表需要更新历史表中的相邻行以避免间隙和重叠。最有可能在历史记录行移动的位置自和行移动的位置到。
Fiddle看看它的实际效果。
关于sql-server - 使用临时表更新 ValidFrom 和 ValidTo 字段会导致奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65126764/