1. 程式人生 > >SQL Server2016新特性(2):時態表 Temporal Table

SQL Server2016新特性(2):時態表 Temporal Table

SQL Server 2016 引入了對版本由系統控制的臨時表的支援,其附帶的內建支援可以提供表中儲存的資料在任意時間點的相關資訊,而不僅僅是資料在當前時刻正確的資訊。 臨時表是 ANSI SQL 2011 中引入的資料庫功能。

版本由系統控制的臨時表是使用者表的一種型別,旨在保留完整的資料更改歷史記錄,並實現輕鬆的時間點分析。 這種型別的臨時表之所以稱為版本由系統控制的臨時表,是因為每一行的有效期由系統(即資料庫引擎)管理。

一、建立時態表

在建立時態表的時候,需要增加3個欄位:

SysStartTime datetime2 GENERATED ALWAYS AS ROW START NOT NULL,
SysEndTime DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME(SysStartTime,SysEndTime)

每個臨時表有兩個顯式定義的列,其中每個列都有一個 datetime2 資料型別。 這些列稱為期限列。 每當修改了某行後,系統將以獨佔方式使用這些期限列來記錄每行的有效期。

也就是說這2個欄位是系統使用的,我們不需要去修改,用來記錄每一行資料的開始時間、無效時間,period就是這個從有效到無效的期間、時間段。

程式碼如下:

CREATE TABLE tb_org
(
org_id INT NOT NULL PRIMARY KEY CLUSTERED,
org_name VARCHAR(30) NOT NULL,
parent_org_id INT NULL,
emp_id INT NULL,
SysStartTime datetime2 GENERATED ALWAYS AS ROW START NOT NULL,
SysEndTime DATETIME2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME(SysStartTime,SysEndTime)
)
WITH(SYSTEM_VERSIONING = ON)

INSERT INTO tb_org(org_id,org_name,parent_org_id,emp_id)
VALUES
(1, '行長', NULL,1),
(2, '常務', 1,2),
(3, '專務', 1,3),
(4, '營業二部部長', 3,4),
(5, '營業二部次長', 4,5);


二、修改資料,查詢修改之前的資料

修改資料,把emp_id改為6:

UPDATE tb_org
SET emp_id = 6
WHERE org_id = 5
查詢修改後的資料,如下圖:



接下來,查詢修改之前的資料,需要注意的是datetime2記錄的是utc時間,而不是本地的時間,所以需要把下面本地的時間2018-01-27 16:46:43 減去8小時的時差,轉成utc時間就是 2018-01-27 08:46:43。

程式碼如下:

SELECT *
FROM tb_org
    FOR SYSTEM_TIME BETWEEN '2018-01-27 00:00:00.0000000' AND '2018-01-27 08:46:43'
WHERE org_id = 5;

查詢結果中是修改之前的資料,emp_id為5:



三、這個修改前的資料是存在哪裡的?

在ssms中,點開tb_org,可以看到有一個歷史表:[dbo].[MSSQL_TemporalHistoryFor_1317579732]



查一下這個表,發現正是這個表裡記錄了修改之前的資料:


最後,如果要刪除tb_org,需要進行如下操作後,才能刪除表,否則會報錯:

DROP TABLE tb_org
/*訊息 13552,級別 16,狀態 1,第 30 行
在表“test.dbo.tb_org”上刪除表操作失敗,因為此操作不是經系統版本控制的臨時表中支援的操作。
*/

--必須要先設定
ALTER TABLE dbo.tb_org SET (SYSTEM_VERSIONING=OFF);

DROP TABLE tb_org;