[SQL SERVER]SQL2016-時態表(1)

Temporal Tables也可稱為系統版本時態表,

該功能允許SQL Server自動記錄資料表歷史紀錄,

主要目的是為了保留資料變更的完整歷程。

建立Temporal Tables自動保留資料變更的完整歷程,

並允許簡單的時間點分析,Temporal Tables上需要有兩個額外的datetime2時間資料行(UTC)定義有效時間,

其有效時間皆由SQL Server資料庫引擎所管理,SQL Server會使用此資料表,

在每次時態表中的資料列進行更新或刪除時,自動儲存資料列的先前版本,

讓我們可以查詢先前版本資料內容,但千萬不要以為Temporal Tables使用來取代CDC

CDC內部運作主要是在日志檔案中擷取所有異動操作歷史記錄,

並將這些訊息寫入對應的跟蹤表,而Temporal Tables是儲存資料表實際資料變更的完整歷程(且保留時間也較長),

這篇我們來看看如何建立Temporal Tables和一些注意事項及應用。

 

主要應用(更多資訊請參考Temporal Table Usage Scenarios)

1修復row-level資料錯誤:假如某一筆資料內容不小心修改錯誤、刪除甚至毀損,就可透過時態表輕易並快速恢復。

2稽核: Temporal Tables可以讓你快速又簡單找出某時段特定資料內容。

 

限制和考量(更多資訊請參考Temporal Table Considerations and Limitations)

不支援FILETABLE。

SYSTEM_TIME資料行必須使用datetime2並not null。

時態表支援 blob 資料類型,但會產生龐大的儲存成本(大小會影響效能)。

不支援TRUNCATE TABLE、不允許直接修改歷程記錄資料表中的資料。

時態表或歷程記錄資料表不允許使用INSTEAD OF 觸發程序,AFTER 觸發程序僅允許針對目前的資料表使用。

歷程記錄資料表必須建立於與目前資料表相同的資料庫中。 不支援針對 Linked Server 的時態查詢。

歷程記錄資料表,建議建立叢集資料列存放區索引或非叢集資料列存放區索引,藉以取得最佳儲存大小和效能。

不行針對SYSTEM_TIME資料行進行UPDATE。

無法對歷史資料表進行資料修改。

 

建立時態表

CREATE TABLE dbo.MyTemporal
	(ID int primary key  --必須定義PK
	,c1 int	
	,c2 AS c1 * .5  --可支援計算資料行
	,c3 varchar(20)
	,StartTime datetime2 GENERATED ALWAYS AS ROW START NOT NULL --定義開始時間
	,EndTime datetime2 GENERATED ALWAYS AS ROW END NOT NULL--定義結束時間
	,PERIOD FOR SYSTEM_TIME (StartTime,EndTime)) 
	WITH(SYSTEM_VERSIONING = ON( HISTORY_TABLE = [dbo].[MyTemporal_Archive] , DATA_CONSISTENCY_CHECK = ON )
	--啟用Temporal並命名歷史紀錄表為MyTemporal_Archive(必須指定結構描述),根據預設,歷程記錄資料表會採 PAGE 壓縮處理。
	); 

CREATE TABLE dbo.MyTemporalB
	(ID int primary key  --必須定義PK
	,c1 int	
	,c2 AS c1 * .5  --可支援計算資料行
	,c3 varchar(20)
	,StartTime datetime2 GENERATED ALWAYS AS ROW START HIDDEN  NOT NULL --定義開始時間並隱藏
	,EndTime datetime2 GENERATED ALWAYS AS ROW END HIDDEN  NOT NULL--定義結束時間並隱藏
	,PERIOD FOR SYSTEM_TIME (StartTime,EndTime)) 
	WITH(SYSTEM_VERSIONING = ON	--啟用Temporal
	);

歷程記錄資料表預設名稱很不友善,建議自行命名。

 

INSERT操作

insert into MyTemporal(ID,c1,c3)
	select 1,10,'rico'
select * from MyTemporal

insert into MyTemporalB(ID,c1,c3)
	select 1,10,'rico'
select * from MyTemporalB

Hidden預設不顯示時間欄位,如需要必須明確寫出資料欄位。

 

注意:Insert操作不會將資料新增至歷史資料表

select * from MyTemporal_Archive
select * from MSSQL_TemporalHistoryFor_1047674780

UPDATE操作

update MyTemporal set c3='sherry'
	where id=1
select * from MyTemporal
select * from MyTemporal_Archive

可以看到前一版本rico資料被儲存在歷史資料表。

 

嘗試更新SYSTEM_TIME資料行會發生錯誤

UPDATE MyTemporal
    set c3='sherry',
    StartTime = GETUTCDATE(),
    EndTime = GETUTCDATE()
    WHERE Id = 1
Msg 13537, Level 16, State 1, Line 22
Cannot update GENERATED ALWAYS columns in table 
'WideWorldImporters.dbo.MyTemporal'.

 

DELETE操作

DELETE MyTemporal WHERE Id = 1
select * from MyTemporal
select * from MyTemporal_Archive

TRUNCATE時態表

TRUNCATE TABLE MyTemporal  --truncate 會失敗
Msg 13545, Level 16, State 1, Line 19
Truncate failed on table 'WideWorldImporters.dbo.MyTemporal' 
because it is not supported operation on system-versioned tables.

 

DROP時態表

--Disabling System Versioning
	alter TABLE dbo.MyTemporalB SET (SYSTEM_VERSIONING = OFF)
	drop table MyTemporalB --歷史資料表也會一併刪除

Enjoy SQL Server 2016

 

參考

Temporal Tables

SQL 2016 – Temporal Tables – What are they and how do you set one up?

Temporal Tables in Sql Server 2016 Part 1: Introduction to Temporal Tables and DML operations on the Temporal Table

[SQL SERVER][CDC]SQL2008新特性-Change Data Capture#1簡介

[SQL SERVER][CDC]SQL2008新特性-Change Data Capture#2測試

[SQL SERVER][CDC]SQL2008新特性-Change Data Capture#3補充