sql-server - 使用临时表更新 ValidFrom 和 ValidTo 字段会导致奇怪的行为

标签 sql-server sql-update temporal-tables

我试图告诉历史表,某个记录在与其原始 ValidFromValidTo 值不同的时间范围内“相关”,如下所示:

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 时间之间“跳过”了几秒钟:

enter image description here

我从未在历史表格中看到过这样的差距..

这是一个错误吗?
有办法克服吗?

最佳答案

说明

如果您更新的历史记录行在 2020-12-03 11:12:07.402020-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/

相关文章:

mysql - SQL UNION ALL 消除重复项

postgresql - 即使我添加了 btree_gist 和 temporal_tables 扩展,也会出现错误 : type "period" does not exist,

sql - 为 SQL 表类型插入批量记录时获取 SCOPE_IDENTITY 值

sql-server - SQL Server - 使用当前的 GetDate 过滤器创建架构绑定(bind)索引 View

SQL 查询仅返回每个组 ID 1 条记录

oracle - 如何避免在 SCHEMA 更改后破坏临时表中的查询?

sql-server - DACPAC 提示带有 FOR SYSTEM_TIME 子句的 View

php - 'login' 中的未知列 'where clause'

MySQL 使用来自另一个表的信息更新一个表

c# - SQL更新语句添加一个值