SQL Server 启用SYSTEM_VERSIONING错误-历史记录表中的日期重叠

7tofc5zh  于 2022-12-17  发布在  其他
关注(0)|答案(3)|浏览(162)

我最近将我的SQL 2019数据库从VM迁移到了Azure SQL。我使用了MS Data Migration工具,但不幸的是,它无法从时态表迁移数据。
因此,我只是使用该工具创建表模式,然后使用SSIS移动数据。
由于我现有的历史记录表中有数据,我想保留SysStartDate和SysEndDate字段。为此,我必须禁用Azure SQL数据库中的SYSTEM_VERSIONING,并删除表中的PERIOD。
数据迁移成功,因此我在表上重新创建了PERIOD,但当我尝试使用指定的历史表启用SYSTEM_VERSIONING时,出现以下错误:
消息13573,级别16,状态0,第34行
将SYSTEM_VERSIONING设置为ON失败,因为历史记录表'xxxxxHistory'
包含重叠记录。
我觉得这很奇怪,因为现有的表最初是作为时态表连接的,所以我不明白为什么现在会有冲突。

ALTER TABLE xxx.xxx 
ADD PERIOD FOR SYSTEM_TIME(SysStartTime, SysEndTime)    

ALTER TABLE xxx.xxx 
SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE=xxx.xxxHistory))

我期望得到一个成功的时态表,但却得到了以下错误:
消息13573,级别16,状态0,第34行
将SYSTEM_VERSIONING设置为ON失败,因为历史记录表'xxxxxHistory'
包含重叠记录。
我运行了以下查询以识别重叠,但没有得到任何重叠:

SELECT 
     xxxxKeyNumeric
     ,SysStartTime
     ,SysEndTime
FROM 
    xxxx.xxxxhistory o
WHERE EXISTS
(
    SELECT 
        1 
    FROM 
        xxxx.xxxxhistory o2
    WHERE 
        o2.xxxxKeyNumeric = o.xxxxKeyNumeric
        AND o2.SysStartTime <= o.SysEndTime
        AND o.SysStartTime <= o2.SysEndTime
        AND o2.xxxxPK != o.xxxxPK
)
ORDER BY 
    o.xxxxKeyNumeric, 
    o.SysStartTime
xdyibdwo

xdyibdwo1#

我找到了这个错误的解释:
“同一记录中有多条记录的开始日期和结束日期重叠。历史记录表中最后一行的结束日期应与父表中活动记录的开始日期匹配”blog of a DBA
在切换历史表、触摸几行、然后试图返回旧的历史表之后,我遇到了这种情况。
UPDATE:又发生了,这一次表有数百万行,我不得不写一个查询,比较历史表中每一行的开始日期和结束日期。
可能原因:
1.**对于每个PK,历史记录行的开始日期和结束日期不得重叠。**以下查询将查找此特定问题。
1.该PK历史记录中最新行的结束日期,其结束日期晚于主表中PK的开始日期。可以修改上述查询来执行此操作
1.在PK相同的行中,2行覆盖相同的时间间隔。如果它们重叠一毫秒,并且有人请求精确的毫秒,它将不知道2个版本中的哪个是正确的。
对于第一期:

select ant.*,post.* , DATEDIFF(day,ant.end_date,post.start_date)
from
(SELECT
      PK_column
    , start_date
    , end_date
    , ROW_NUMBER() OVER(PARTITION BY PK_column ORDER BY end_date desc, start_date desc)    AS current
    ,(ROW_NUMBER() OVER(PARTITION BY PK_column ORDER BY end_date desc, start_date desc))-1 AS previous
FROM huge_table_HIST 
) ant
inner join
(SELECT
      key_column
    , start_date
    , end_date
    , ROW_NUMBER() OVER(PARTITION BY PK_column ORDER BY end_date desc, start_date desc ) AS current
    FROM huge_table_HIST 
) post
ON ant.PK_column=post.PK_column AND ant.previous=post.current
WHERE ant.end_date > post.start_date

令人惊讶的是,在以下情况下不会失败:

  • 对于相同的PK,您有多个行具有完全相同的开始、结束和结束日期。SQL Server似乎将它们视为空间中的单个点,而不是间隔。只有当您请求它们存在的精确毫秒时,它们才会显示。
  • 历史记录行的结束日期和下一行的开始日期之间存在间隔。SQL Server认为PK在该时间间隔内不存在。
h79rfbju

h79rfbju2#

时态表依赖于时态表的主键值,并结合SysStartTime来确定历史表中的唯一性。
如果你修改了主键定义,这很容易发生。另外,如果你的历史表中对应于时态表的PK的字段没有被填充,或者很多/所有字段都被填充了默认值,那么重叠就会被检测到,你就会得到那个错误。
检查PK是否在系统版本化时态表中定义,然后检查历史表主键字段中的相应值是否正确(即,对于任何给定的PK & SysStartTime值都是唯一的)。
在再次应用系统版本关系之前,您可能必须相应地更新历史记录表。

ki0zmccv

ki0zmccv3#

当任何给定的主键有多个记录时,也会发生此错误
GENERATED ALWAYS AS ROW START列或GENERATED ALWAYS AS ROW END列。
以下查询将有助于识别这些记录。

select ID
from dbo.HistoryTable  
group by ID, SysStartTime 
having count(*) > 1

select ID
from dbo.HistoryTable  
group by ID, SysEndTime 
having count(*) > 1

相关问题