対象者:SQL Server 2016 (13.x) およびそれ以降のバージョン
Azure SQL Database
Azure SQL Managed Instance
SQL Database in Microsoft Fabric
履歴テーブルの指定方法に基づいて、システムバージョン対応の時間テーブルを作成する方法は3つあります:
匿名 の履歴テーブルを持つ時間テーブル:現在のテーブルのスキーマを指定し、システムが自動生成名で対応する履歴テーブルを作成させます。
既定の履歴テーブルでのテンポラル テーブル: 履歴テーブルのスキーマ名とテーブル名を指定し、システムがそのスキーマで履歴テーブルを作成できるようにします。
あらかじめ作成してあるユーザー定義履歴テーブルでのテンポラル テーブル: ニーズに最適な履歴テーブルをユーザーが作成し、テンポラル テーブルの作成時にそのテーブルを参照します。
匿名履歴テーブルによりテンポラル テーブルを作成する
匿名履歴テーブルを使用したテンポラル テーブルの作成は、すばやくオブジェクトを作成するための便利なオプションであり、プロトタイプおよびテスト環境で特に有効です。 また、 SYSTEM_VERSIONING 節のパラメータを必要としないため、時間テーブルを作成する最も簡単な方法でもあります。 以下の例では、履歴テーブルの名前を定義せずに、システムのバージョン管理が有効化された新しいテーブルを作成します。
CREATE TABLE Department
(
DeptID INT NOT NULL PRIMARY KEY CLUSTERED,
DeptName VARCHAR (50) NOT NULL,
ManagerID INT NULL,
ParentDeptID INT NULL,
ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL,
ValidTo DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
)
WITH (
SYSTEM_VERSIONING = ON
);
Remarks
システム バージョン管理のテンポラル テーブルでは、主キーが定義されている必要があり、さらに、PERIOD FOR SYSTEM_TIME または として宣言された 2 つの GENERATED ALWAYS AS ROW START 列で定義された GENERATED ALWAYS AS ROW END がちょうど 1 つ定義されている必要があります。
PERIOD 列は、null 値許容性が指定されていない場合でも、常に null 値非許容と見なされます。
PERIOD 列が明示的に Null 許容として定義されている場合、CREATE TABLE ステートメントは失敗します。
履歴テーブルは、列の数、列名、順序、データ型に関して、常に現在のテーブルまたはテンポラル テーブルとスキーマが整合している必要があります。
データベース エンジンは、現在または時間テーブルと同じスキーマ内で匿名の履歴テーブルを自動的に作成します。
匿名履歴テーブル名は次の形式になります: MSSQL_TemporalHistoryFor_<current_temporal_table_object_id>_<suffix>。 サフィックスは省略可能であり、テーブル名の最初の部分が一意ではない場合にのみ追加されます。
履歴テーブルは、行ストア テーブルとして作成されます。 可能な場合は PAGE の圧縮が適用されます。不可能な場合は、履歴テーブルは圧縮されません。 たとえば、SPARSE 列などの一部のテーブル構成では、圧縮は許可されません。
履歴テーブルには、IX_<history_table_name> 形式の自動生成名を持つ既定のクラスター化インデックスが作成されます。 クラスター化インデックスには、 PERIOD 列 (終了、開始) が含まれます。
Fabric SQL データベースでは、作成された履歴テーブルは Fabric OneLake にミラーリングされません。
メモリ最適化テーブルとして現在のテーブルを作成する場合は、「メモリ最適化テーブルでのシステム バージョン管理されたテンポラル テーブル」を参照してください。
既定の履歴テーブルによるテンポラル テーブルの作成
既定の履歴テーブルによるテンポラル テーブルの作成は、名前付けを制御しながら、一方で既定の構成による履歴テーブルの作成はシステムに任せたい場合に、便利なオプションです。 以下の例では、システムバージョン管理が有効化された新しいテーブルを作成し、履歴テーブルの名前を明示的に定義します。
CREATE TABLE Department
(
DeptID INT NOT NULL PRIMARY KEY CLUSTERED,
DeptName VARCHAR (50) NOT NULL,
ManagerID INT NULL,
ParentDeptID INT NULL,
ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL,
ValidTo DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
)
WITH (
SYSTEM_VERSIONING = ON (
HISTORY_TABLE = dbo.DepartmentHistory
)
);
Remarks
履歴テーブルは "匿名" 履歴テーブルの作成に適用されるのと同じ規則を使用して作成されますが、以下の規則は名前付き履歴テーブルだけに適用されます。
HISTORY_TABLEパラメーターにはスキーマ名が必須です。指定したスキーマが存在しない場合、
CREATE TABLEステートメントは失敗します。HISTORY_TABLEパラメーターによって指定されているテーブルが既に存在する場合、新しく作成されるテンポラル テーブルに対して、スキーマの整合性およびテンポラル データの整合性が検証されます。 無効な履歴テーブルが指定された場合、CREATE TABLEステートメントは失敗します。
ユーザー定義の履歴テーブルを使用したテンポラル テーブルの作成
ユーザー定義の履歴テーブルで時間テーブルを作成することは、特定のストレージオプションや履歴クエリに合わせて調整された異なるインデックスを持つ履歴テーブルを指定する際に便利な選択肢です。 以下の例では、時間テーブルに整合したスキーマを持つユーザー定義の履歴テーブルを作成します。 この履歴テーブルにはクラスタ化されたカラムストアインデックスと、ポイント検索用の非クラスタ化された行ストア(Bツリー)インデックスが備わっています。 履歴テーブルを作成した後、時間テーブルを作成し、ユーザー定義の履歴テーブルをデフォルトの履歴テーブルとして指定します。
Note
ドキュメントでは、一般的にインデックスに関して B ツリーという用語が使用されます。 行ストア インデックスで、データベース エンジンによって B+ ツリーが実装されます。 これは、列ストア インデックスやメモリ最適化テーブルのインデックスには適用されません。 詳細については、「SQL Server と Azure SQL のインデックスのアーキテクチャとデザイン ガイド」を参照してください。
CREATE TABLE DepartmentHistory
(
DeptID INT NOT NULL,
DeptName VARCHAR (50) NOT NULL,
ManagerID INT NULL,
ParentDeptID INT NULL,
ValidFrom DATETIME2 NOT NULL,
ValidTo DATETIME2 NOT NULL
);
GO
CREATE CLUSTERED COLUMNSTORE INDEX IX_DepartmentHistory
ON DepartmentHistory;
CREATE NONCLUSTERED INDEX IX_DepartmentHistory_ID_Period_Columns
ON DepartmentHistory(ValidTo, ValidFrom, DeptID);
GO
CREATE TABLE Department
(
DeptID INT NOT NULL PRIMARY KEY CLUSTERED,
DeptName VARCHAR (50) NOT NULL,
ManagerID INT NULL,
ParentDeptID INT NULL,
ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL,
ValidTo DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
)
WITH (
SYSTEM_VERSIONING = ON (
HISTORY_TABLE = dbo.DepartmentHistory
)
);
Remarks
過去のデータに対して集約やウィンドウ関数を用いる解析クエリを実行する予定がある場合、圧縮とクエリ性能のためにクラスタ化されたカラムストアをプライマリインデックスとして作成することが強く推奨されます。
テンポラル テーブルをデータの監査に使用する場合は (つまり、現在のテーブルから単一行の変更履歴を検索する場合)、クラスター化インデックスを含む行ストア履歴テーブルを作成する必要があります。
履歴テーブルに、主キー、外部キー、一意なインデックス、テーブル制約、トリガーを含めることはできません。 変更データ キャプチャ、変更追跡、トランザクション レプリケーション、またはマージ レプリケーション用に構成することはできません。
Fabric SQL データベースと Fabric ミラーリングが構成された Azure SQL Database では、テンポラル テーブルの作成時に履歴テーブルとして既存のテーブルを使用すると、既存のテーブルのミラー化が停止します。
非テンポラル テーブルをシステム バージョン管理されたテンポラル テーブルに変更する
既存の非テンポラルテーブルでシステムバージョン管理を有効にすることも可能で、カスタムテンポラルソリューションを組み込みサポートに移行したい場合などです。
たとえば、一連のテーブルにトリガーを使用してバージョン管理を実装できます。 テンポラル システム バージョン管理を使用すると、それほど複雑ではなく、他にも次のような利点もあります。
- 変更できない履歴
- タイム トラベル クエリ用の新しい構文
- DML パフォーマンスの向上
- 最小限のメンテナンス コスト
既存のテーブルを変換する際は、 HIDDEN 節を使って新しい PERIOD 列( datetime2 列 ValidFrom と第 ValidTo)を隠すことを検討してください。これにより、列名が明示的に指定されていない既存のアプリケーション(例: SELECT * や INSERT 、カラムリストなし)や新しいカラム対応に設計されていないアプリケーションには影響が出ないようにしましょう。
非テンポラル テーブルへのバージョン管理の追加
データを含む非テンポラル テーブルの変更の追跡を開始する場合は、PERIOD 定義を追加する必要があり、必要に応じて、SQL Server で作成される空の履歴テーブルの名前を指定します。
CREATE SCHEMA History;
GO
ALTER TABLE InsurancePolicy
ADD ValidFrom DATETIME2 GENERATED ALWAYS AS ROW START HIDDEN
CONSTRAINT DF_InsurancePolicy_ValidFrom DEFAULT SYSUTCDATETIME(),
ValidTo DATETIME2 GENERATED ALWAYS AS ROW END HIDDEN
CONSTRAINT DF_InsurancePolicy_ValidTo DEFAULT CONVERT (DATETIME2, '9999-12-31 23:59:59.9999999'),
PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo);
GO
ALTER TABLE InsurancePolicy
SET (
SYSTEM_VERSIONING = ON (
HISTORY_TABLE = History.InsurancePolicy
)
);
GO
Important
DATETIME2 の精度は、基になるテーブルの精度に合わせる必要があります。
Remarks
データを含む既存のテーブルに既定値を持つ NULL 非許容列を追加することは、SQL Server Enterprise Edition を除くすべてのエディションではデータ サイズ操作です (そのエディションではメタデータ操作です)。 SQL Server Standard Edition では、データが含まれる既存の大規模な履歴テーブルの場合、非 null 列の追加はコストのかかる操作になることがあります。
期間開始列および期間終了列に対する制約は、慎重に選択する必要があります。
開始列の既定値では、既存の行が有効であると考慮することを始める時点を指定します。 未来の時刻は指定できません。
終了日時は、特定の datetime2 精度に対する最大値として指定する必要があります。たとえば、
9999-12-31 23:59:59や9999-12-31 23:59:59.9999999にします。
PERIODを追加すると、現在のテーブルに対してデータの整合性チェックを行い、ピリオル列の既存の値が有効かどうかを確認します。
SYSTEM_VERSIONING を有効にするときに既存の履歴テーブルが指定されている場合、現在のテーブルと履歴テーブルの両方に対してデータの整合性チェックが行われます。
DATA_CONSISTENCY_CHECK = OFF を追加パラメーターとして指定した場合は、スキップできます。
既存のテーブルを組み込みサポートに移行する
この例では、トリガーに基づく既存のソリューションから組み込みのテンポラル サポートに移行する方法を示します。 この例は、現在のカスタムソリューションが現在および過去のデータを2つの別々のユーザーテーブル(ProjectTaskCurrent と ProjectTaskHistory)に分割することを前提としています。
既存のソリューションが実際の行と過去行を1つのテーブルに保存している場合は、以下の例で示す移行ステップの前にデータを2つのテーブルに分割すべきです。 最初に、将来のテンポラル テーブルでトリガーを削除します。 次に、PERIOD 列を null 非許容にします。
/* Drop trigger on future temporal table */
DROP TRIGGER ProjectCurrent_OnUpdateDelete;
/* Make sure future period columns are non-nullable */
ALTER TABLE ProjectTaskCurrent
ALTER COLUMN [ValidFrom] DATETIME2 NOT NULL;
ALTER TABLE ProjectTaskCurrent
ALTER COLUMN [ValidTo] DATETIME2 NOT NULL;
ALTER TABLE ProjectTaskHistory
ALTER COLUMN [ValidFrom] DATETIME2 NOT NULL;
ALTER TABLE ProjectTaskHistory
ALTER COLUMN [ValidTo] DATETIME2 NOT NULL;
ALTER TABLE ProjectTaskCurrent
ADD PERIOD FOR SYSTEM_TIME ([ValidFrom], [ValidTo]);
ALTER TABLE ProjectTaskCurrent
SET (
SYSTEM_VERSIONING = ON (
HISTORY_TABLE = dbo.ProjectTaskHistory,
DATA_CONSISTENCY_CHECK = ON
)
);
Remarks
PERIOD 定義内の既存の列を参照すると、それらの列の generated_always_type が AS_ROW_START および AS_ROW_END に暗黙的に変更されます。
PERIODを追加すると、現在のテーブルに対してデータの整合性チェックを行い、ピリオル列の既存の値が有効かどうかを確認します。
SYSTEM_VERSIONING と DATA_CONSISTENCY_CHECK = ON を設定し、既存データに対するデータ整合性チェックを強制的に行うことを強くお勧めします。
隠れ列を好む場合は、以下のコマンドを使用します。
ALTER TABLE [tableName]
ALTER COLUMN [columnName] ADD HIDDEN;
関連するコンテンツ
- テンポラル テーブル
- システム バージョン管理テンポラル テーブルの使用を開始する
- システム バージョン管理されたテンポラル テーブルの履歴データの保有期間管理
- メモリ最適化テーブルを使用したシステム バージョン管理されたテンポラル テーブル
- CREATE TABLE (Transact-SQL)
- システム バージョン管理されたテンポラル テーブル内のデータを変更する
- システム バージョン管理されたテンポラル テーブル内のデータに対してクエリを実行する
- システム バージョン管理されたテンポラル テーブルのスキーマを変更する
- システム バージョン管理テンポラル テーブルでシステム バージョン管理を停止する