天天看點

SQL Server 2016新特性:Temporal Table

什麼是系統版本的Temporal Table

系統版本的Temporal Table是可以儲存曆史修改資料并且可以簡單的指定時間分析的使用者表。 這個Temporal Table就是系統版本的Temporal Table因為每行的有效期由系統托管的。

每個Temporal Table有2個顯示定義的列,類型是datetime2。這些用來表示有效期。這個列用來标記這個行是不是在期間内可用。

除了上面的period列,l臨時表也包含了引用到其他表,系統使用這個表來儲存行修改删除前的行版本。這個附加表可以認為是history表,主表包含了目前的行版本為目前表。在Temporal Table建立的時候可以指定一個history表或者讓系統建立一個預設的history表。

臨時表的工作原理

系統版本的表是有一對表,目前表和曆史表。這些表都包含2個額外的datetime2字段用來定義每個行的可用期限:

期限開始列:系統把行的開始時間記錄在這個列上,稱為SysStartTime

期限結束列:系統把行的結束時間記錄在這個列上,稱為SysEndTime

目前表包含了每個行的目前值。曆史表包含每個行的之前的隻,starttime,endtime表示行的可用期限。

SQL Server 2016新特性:Temporal Table

以下是一個例子:

CREATE TABLE dbo.Employee  

(   

  [EmployeeID] int NOT NULL PRIMARY KEY CLUSTERED  

  , [Name] nvarchar(100) NOT NULL 

  , [Position] varchar(100) NOT NULL  

  , [Department] varchar(100) NOT NULL 

  , [Address] nvarchar(1024) NOT NULL 

  , [AnnualSalary] decimal (10,2) NOT NULL 

  , [ValidFrom] datetime2 (2) GENERATED ALWAYS AS ROW START 

  , [ValidTo] datetime2 (2) GENERATED ALWAYS AS ROW END 

  , PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo) 

 )   

 WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.EmployeeHistory));

可以删除括号中的HISTORY_TABLE系統會自動建立history表。

INSERT:對于一個insert,系統會設定SysStartTime列為目前事務的開始時間,SysEndTime為最大的值9999-12-31

UPDATE:對于update,系統會報之前的行儲存到曆史表并且設定SysEndTime為目前事務的啟動時間。行被關閉,這個期限就是這個行的可用期限。這個行在目前表上的值被修改,那麼SysStartTime被設定為目前事務的開始時間。SysEndTime被設定為最大時間。

DELETE:對于删除,系統把之前的行儲存到history表,并且設定SysEndtime為事務的開始時間。标記行關閉,期限記錄表示行的可用期限。目前表中行被删除。目前的查詢不會被查到目前行。隻有帶時間的查詢,或者直接查詢曆史表才能查到這個行。

MERGE:對于MERGE涉及到3個操作INSERT,UPDATE,DELETE,根據操作的不同做不同的記錄。

臨時資料查詢

可以使用select from的for system_time子句來查詢目前表和曆史表的資料。

SQL Server 2016新特性:Temporal Table

以下是查詢的例子:

SELECT * FROM Employee  

    FOR SYSTEM_TIME   

        BETWEEN '2014-01-01 00:00:00.0000000' AND '2015-01-01 00:00:00.0000000'  

            WHERE EmployeeID = 1000 ORDER BY ValidFrom;

注意:

FOR SYSTEM_TIME會過濾掉SysStartTime=SysEndTime的資料。這些行在同一個事務裡面操作了同一行兒産生。隻能通過查詢曆史表才能傳回

關于SYSTEM_TIME過濾

表達式

符合條件的行

Description

AS OF<date_time>

SysStartTime <= date_time AND SysEndTime > date_time

傳回一個表,其行中包含過去指定時間點的實際(目前)值。 在内部,臨時表及其曆史記錄表之間将進行聯合,然後篩選結果以傳回在 <date_time> 參數指定的時間點有效的行中的值。 如果 system_start_time_column_name 值小于或等于 <date_time> 參數值,并且 system_end_time_column_name 值大于 <date_time> 參數值,則此行的值視為有效。

FROM<start_date_time>TO<end_date_time>

SysStartTime < end_date_time AND SysEndTime > start_date_time

傳回一個表,其中包含在指定的時間範圍内保持活動狀态的所有行版本的值,不管這些版本是在 FROM 自變量的 <start_date_time> 參數之前開始活動,還是在 TO 自變量的 <end_date_time> 參數值之後停止活動。 在内部,将在臨時表及其曆史記錄表之間進行聯合,然後篩選結果,以傳回在指定時間範圍内任意時間保持活動狀态的所有行版本的值。 正好在 FROM 終結點定義的下限時間停止活動的行将被排除,正好在 TO 終結點定義的上限時間開始活動的記錄也将被排除。

BETWEEN<start_date_time>AND<end_date_time>

SysStartTime <= end_date_time AND SysEndTime > start_date_time

與上面的 FOR SYSTEM_TIME FROM <start_date_time>TO<end_date_time> 描述相同,不過,傳回的行表包括在 <end_date_time> 終結點定義的上限時間激活的行。

CONTAINED IN (<start_date_time> , <end_date_time>)

SysStartTime >= start_date_time AND SysEndTime <= end_date_time

傳回一個表,其中包含在 CONTAINED IN 參數的兩個日期時間值定義的時間範圍内打開和關閉的所有行版本的值。 正好在下限時間激活的記錄,或者在上限時間停止活動的行将包括在内。

ALL

所有行

傳回屬于目前表和曆史記錄表的行的聯合。

可以通過Hidden隐藏期限列,删除表需要先關閉系統版本 ALTER TABLE Employee SET (SYSTEM_VERSIONING =off )之後才能删除表