天天看點

SQL Server 2016新功能--Temporal Table--快速恢複誤操作

Temporal Table是 SQL Server 2016的一個新特性,我們可以稱之為曆史記錄表,它能記錄表中任何時間點所做的資料改動。有了這個功能,就能夠在發生誤操作的情況下及時對資料進行恢複。

先簡單介紹一下這個新特性,啟用Temporal Table 功能後表結構如下圖所示:

SQL Server 2016新功能--Temporal Table--快速恢複誤操作

可以看到,啟用Temporal Table 後,在主表中多了一張曆史記錄表,曆史表中就記錄了所有的資料改動。而且表中還多了2個字段,SysTimeStart和 SysTimeEnd,這2個字段類型都是datetime2,多出來的這2個字段記錄了資料發生變動的時間。

向表寫入資料時如下所示:

SQL Server 2016新功能--Temporal Table--快速恢複誤操作

SysTimeStart和SysTimeEnd 2個字段是由SQL Server自動寫入的,記錄了資料的操作時間,後面會詳細介紹。可以看到,SysTimeStart的時間和寫入資料的時間不一樣,是因為SysTimeStart和SysTimeEnd 所使用的是UTC格式的時間。UTC+時區=本地時間,是以SysTimeStart 的時間與本地時間要差8小時。

接下來我們詳細介紹 Temporal Table功能

使用Temporal Table功能的條件:

1,必須要有主鍵。

2,必須定義兩個資料類型為datetime2的列,用來記錄開始和結束時間點,如上面圖檔中的SysTimeStart 和SysTimeEnd 。且字段不能為NULL。

3,曆史表必須和主表的結構一摸一樣,包括字段名字和資料類型。

使用下面的語句建立有 Temporal Table 功能的表 

CREATE TABLE Test_TemporalTable(
	ID INT IDENTITY(1,1) PRIMARY KEY ,
	Names VARCHAR(10) , 
	SysTimeStart DATETIME2 GENERATED ALWAYS AS ROW START NOT NULL ,
	SysTimeEnd DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL ,
	PERIOD FOR SYSTEM_TIME(SysTimeStart,SysTimeEnd)
) WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.Test_TemporalTableHistroy)) ;
           

建立完成後,如下圖所示:

SQL Server 2016新功能--Temporal Table--快速恢複誤操作

曆史記錄表的列與主表的列完全一樣,但所有的限制會被移除。曆史記錄表可以有自己的索引和統計資訊,也可以在曆史表上建立索引,提高曆史記錄表的性能

如果沒有指定曆史記錄表的名稱,SQL Server将自動生成一個dbo.MSSQL_TemporalHistoryFor_xxx的曆史表,其中xxx是主表的object id,自動生成的表名效果如下圖所示:

SQL Server 2016新功能--Temporal Table--快速恢複誤操作

使用曆史表功能

首先向主表中寫入一些資料

INSERT INTO Test_TemporalTable (Names) VALUES ('Tom'),('Jakey'),('張三'),('李四')
           

寫入資料後,我們查詢主表和曆史記錄表,可以看到,曆史記錄表中并沒有資料。且主表中 SysTimeStart  和 SysTimeEnd 由SQL Server自動填上資料,後面将會說明這兩個字段的意義。

SQL Server 2016新功能--Temporal Table--快速恢複誤操作

現在來修改和删除表中的資料

UPDATE Test_TemporalTable SET Names = '王五' WHERE ID = 1 

DELETE Test_TemporalTable WHERE ID = 2
           

再查詢兩張表,就會看到,曆史記錄表中已經把操作的資料記錄了下來,并且記錄下了操作的時間(Histroy表中的SysTimeEnd字段)

SQL Server 2016新功能--Temporal Table--快速恢複誤操作

簡單說明一下:

Temporal Table功能其實是對兩張資料庫表進行了資料版本化(System-versioning)。一張是主表,一張是主表的曆史記錄表。Temporal Table的條件之一是添加兩個類型為datetime2的字段來辨別記錄資料的時間範圍 ( SysTimeStart和SysTimeEnd)。這兩個字段是由SQL Server自動進行維護的,可以在建表的時候對字段加入HIDDEN關鍵字把字段隐藏,這樣就避免兩個字段在SELECT * FROM或者INSERT INTO的時候出現在清單裡面。

當寫入(insert)時,寫入的時間會被寫入到主表的SysTimeStart字段中,SysTimeEnd 則被記錄為'9999-12-31 23:59:59.9999999',曆史記錄表不會有任何記錄。

當更新(update)發生時,曆史記錄表中的SysTimeStart會記錄原資料寫入的時間,SysTimeEnd會記錄本次更新的時間,主表的SysTimeStart則被更新為本次更新的時間,SysEndTime依舊還是'9999-12-31 23:59:59.9999999'。

當删除(delete)發生時,曆史記錄表中的SysTimeStart會記錄原資料寫入的時間,SysTimeEnd會記錄本次删除操作的時間

如果一行資料再次發生Update操作,則在曆史記錄表中會再生産一行記錄,将原表的值以及操作時間記錄下來。

SQL Server 2016新功能--Temporal Table--快速恢複誤操作

有了曆史記錄表中的資料,我們就能在發生誤操作的時候,及時的将資料恢複,再不用還原備份才能恢複資料了,而且還可以根據時間來恢複資料。

有了這個新功能後,怎樣将現有的表轉換成Temporal Table的表呢?

要将現有表轉換成Temporal Table功能的表,分2種情況,一種是現有的表中沒有資料,是空表,一種是現有的表中已有資料,非空表。

下面來分情況轉換

1,将空表轉換成Temporal Table

/*建立一張空表,将空表轉換成Temporal Table*/
CREATE TABLE dbo.Test_TemporalTable_New
(
    ID INT IDENTITY(1,1) PRIMARY KEY ,
    Names VARCHAR(10)
)
GO

SELECT * FROM dbo.Test_TemporalTable_New

GO

---将空表轉換成Temporal Table
ALTER TABLE dbo.Test_TemporalTable_New
ADD SysTimeStart DATETIME2 GENERATED ALWAYS AS ROW START
CONSTRAINT DF_Test_TemporalTable_New_SysStart DEFAULT SYSUTCDATETIME() ,
SysTimeEnd DATETIME2 GENERATED ALWAYS AS ROW END
CONSTRAINT DF_Test_TemporalTable_New_SysEnd DEFAULT CONVERT(datetime2 (0), '9999-12-31 23:59:59.9999999'),
PERIOD FOR SYSTEM_TIME (SysTimeStart, SysTimeEnd)
GO

ALTER TABLE dbo.Test_TemporalTable_New
SET ( SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.Test_TemporalTable_New_History, DATA_CONSISTENCY_CHECK = ON));
GO
           

代碼中 DATA_CONSISTENCY_CHECK 隻是檢查 SysTimeStart 是否小于等于 SysTimeEnd

轉換後的效果如下圖所示:

SQL Server 2016新功能--Temporal Table--快速恢複誤操作

2,将有資料的表轉換成 Temporal Table 有資料的表轉換比空表轉換多出一個步驟。

/*将有資料的表轉換成Temporal Table,一步一步做*/
ALTER TABLE dbo.Test_TemporalTable_Data
ADD SysTimeStart DATETIME2 NOT NULL  CONSTRAINT DF_Test_TemporalTable_Data_SysStart DEFAULT SYSUTCDATETIME() ,
    SysTimeEnd DATETIME2 NOT NULL CONSTRAINT DF_Test_TemporalTable_Data_SysEnd DEFAULT CONVERT(DATETIME2, '9999-12-31 23:59:59.9999999')

GO

ALTER TABLE dbo.Test_TemporalTable_Data
ADD PERIOD FOR SYSTEM_TIME (SysTimeStart, SysTimeEnd);
GO

ALTER TABLE dbo.Test_TemporalTable_Data
SET ( SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.Test_TemporalTable_Data_History, DATA_CONSISTENCY_CHECK = ON));
GO
           

轉換後的效果如下圖所示:

SQL Server 2016新功能--Temporal Table--快速恢複誤操作

繼續閱讀