web-dev-qa-db-ja.com

テーブルのSYSTEM_TIMEにPERIODを追加できませんでした

私が持っています:

  • 既存のデータを含むテーブル
  • SQL Server 2016 SP1
  • SQL Server Management Studio 17.5

次のステートメントを使用して、テーブルを一時テーブルにしています。

ALTER TABLE [dbo].[AnalysisCustomRollupsV2JoinGroups]
ADD [SysStartTime] DATETIME2(0) GENERATED ALWAYS AS ROW START HIDDEN CONSTRAINT DF_AnalysisCustomRollupsV2JoinGroups_SysStart DEFAULT GETUTCDATE()  
   ,[SysEndTime] DATETIME2(0) GENERATED ALWAYS AS ROW END HIDDEN CONSTRAINT DF_AnalysisCustomRollupsV2JoinGroups_SysEnd DEFAULT CONVERT(DATETIME2(0), '9999-12-31 23:59:59'),   
PERIOD FOR SYSTEM_TIME ([SysStartTime], [SysEndTime]); 

ALTER TABLE [dbo].[AnalysisCustomRollupsV2JoinGroups]   
SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.AnalysisCustomRollupsV2JoinGroupsChanges));

問題:

私のローカルSQLインスタンスには多くのデータベースがあります。一部のクエリでクエリが正常に実行されるのは非常に奇妙で、一部のクエリでは次のエラーが発生します。

メッセージ13542、レベル16、状態0、行51テーブル 'dbo.AnalysisCustomRollupsV2JoinGroups'のSYSTEM_TIMEのADD PERIODは、期間の開始が将来の値に設定されたオープンレコードがあるため失敗しました。

クエリをデバッグ/実行しているときに、最初のクエリが正常に実行されることがあります。

私は、これはテーブルに既存のデータがあるためと考えられます。だから、私はこのようにロジックを変更しました:

  • バッファテーブルを作成し、すべてのレコードを入力します
  • 元のテーブルからレコードを削除する
  • テンポラルテーブルを作成する
  • レコードを戻し、バッファテーブルを削除する

繰り返しになりますが、一部のデータベースでは問題ありません。私が持っている問題を解決しようとしています found 以下:

StartDateには、現在のUTC日付を指定しました。これは、将来ではない任意の日付と時刻にすることができますが、UTCの日付である必要があります。現在イギリスの夏時間を利用しているため、GETDATEを使用しようとすると、次のエラーが発生します。メッセージ13542、レベル16、状態0、行51テーブル 'TestAudit.dbo.SomeData'にSYSTEM_TIMEのPERIODを追加期間の開始が将来の値に設定されたオープンレコードがあるため、失敗しました。

上記の意味は何ですか?マシンの時間を変更する必要がありますか?または、私のローカルマシンがUTC時間になっていないため、このエラーが時々発生しますか?

7
gotqn

私は自分の問題を解決する方法を見つけたと思いますが、問題の原因を説明できず、いつでも機能することを保証できないため、これを回答として受け入れるつもりはありません。それは多くのテストの後に発見された修正であり、誰かがここにより多くの光をもたらすことができれば私は嬉しいでしょう。


私は_datetime2_を正確に使用したことがありません。そこで、この形式のソースに戻りましたdatetime2(0)- 非時間テーブルをシステムバージョンの時間テーブルに変更 。私が使用しているスクリプトとの唯一の違いは、日付時刻関数でした。私はGETUTCDATE()を使用しました。datetime(0)(_2018-03-15 07:21:02_など)で厳密にする必要はなく、この例ではSYSUTCDATETIME()です。だから、私はそれを変更しました。

データベースが存在する場合はそれを削除し、バックアップからデータベースを復元し、ループでコードを実行するスクリプトを作成しました(エラーが発生することがあり、再現が非常に困難であると言ったように)。

スクリプトを何度も実行しましたが、失敗の数が異なります(70%の場合もあれば、50%の場合もあれば、以下の場合もあります)。

enter image description here

私はこれを発見しました GETUTCDATEがSYSDATETIMEOFFSETよりも早いのはなぜですか? 新旧の日時関数の違いについての議論。次に、次のクエリを作成します。

_DECLARE @UTC DATETIME2(0) = GETUTCDATE();
DECLARE @SYSUTC DATETIME2(0) = SYSUTCDATETIME();

WHILE DATEPART(SECOND, @UTC) = DATEPART(SECOND, @SYSUTC)
BEGIN;
    SET @UTC  = GETUTCDATE();
    SET @SYSUTC  = SYSUTCDATETIME();
END;

SELECT @UTC AS [UTC]
      ,@SYSUTC AS [SYS UTC]
      ,DATEPART(SECOND, @UTC) AS [UTC sec]
      ,DATEPART(SECOND, @SYSUTC) AS [SYS UTC sec]
      ,CASE WHEN @UTC < @SYSUTC THEN 1 ELSE 0 END AS [TimeTravelPossible]
      ,CONVERT(DATETIME2(0), @UTC) AS [UTC date]
      ,CONVERT(DATETIME2(0), @SYSUTC) AS [SYS UTC date]
      ,IIF(CONVERT(DATETIME2(0), @UTC) = CONVERT(DATETIME2(0), @SYSUTC), 1, 0) AS [Are The Same];
_

私は、sys日付時刻関数ではなくsysを使用して、異なるdatetime2(0)日付を取得できるかどうかを確認したかっただけです。そしてもちろん可能です。

enter image description here

多分、エンジンが行っているチェックはこのようなことをしていて、現在の日付を私の新しい日付と比較して、これがエラーの原因です-_open records with start of period set to a value in the future._

私はこのようにスクリプトを変更して、昨夜1000回実行しました-エラーは生成されませんでした。したがって、この特定の問題は修正したと思いますが、確信が持てません。

_ALTER TABLE [dbo].[AnalysisCustomRollupsV2JoinGroups]
ADD [SysStartTime] DATETIME2 GENERATED ALWAYS AS ROW START HIDDEN CONSTRAINT DF_AnalysisCustomRollupsV2JoinGroups_SysStart DEFAULT SYSUTCDATETIME()  
   ,[SysEndTime] DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN CONSTRAINT DF_AnalysisCustomRollupsV2JoinGroups_SysEnd DEFAULT CONVERT(DATETIME2, '9999-12-31 23:59:59.9999999'),   
PERIOD FOR SYSTEM_TIME ([SysStartTime], [SysEndTime]); 

ALTER TABLE [dbo].[AnalysisCustomRollupsV2JoinGroups]   
SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.AnalysisCustomRollupsV2JoinGroupsChanges));
_
4
gotqn