Temporal Tables – Simple Guide to implement History Tables using SQL Server 2016/2017–Part 3–Modifying Temporal Tables, Disabling System Versioning and why we need to disable


Part 1 – How to create Temporal tables

Part 2 – Accessing History data from Temporal Tables

In this post we will how to modify Temporal Tables, How to disable System Versioning in Temporal tables to update large set data of without affecting history or truncate tables

Modifying Temporal Tables

For adding new columns to Temporal tables, Please use below command

ALTER TABLE dbo.Demo ADD DemoDesc VARCHAR(255) NULL

Screenshot before adding the new column

capture20171022142508566

Screenshot after adding the new column – If we notice, adding the column in the main table automatically modifies the history table as well

capture20171022142736382

Similarly we can modify the tables to drop column or increasing the size of the field, but some of the changes to table are not supported ex. Adding Identify column or changing the data type of the field which is not supported using implicit conversion, in that scenario we need to disable the system versioning to make changes

Disable System Versioning

Screenshot before disabling system versioning

capture20171022143805111

Script to disable system versioning

ALTER TABLE dbo.Demo	SET (SYSTEM_VERSIONING = OFF);

Screenshot after disabling system versioning – If we notice the System versioning is disabled and both Main and history table is displayed as regular tables now

capture20171022143922452

There are other scenarios we need to disable System versioning, if we need to do any of the following operations

1. TRUNCATE TABLE on Main or History table

Msg 13545, Level 16, State 1, Line 1
Truncate failed on table ‘SQL2017_DEMO.dbo.Demo’ because it is not a supported operation on system-versioned tables.

2. Deleting rows from History table

Msg 13560, Level 16, State 1, Line 4
Cannot delete rows from a temporal history table ‘SQL2017_DEMO.dbo.DemoHistory’.

3. Dropping Main or History table

Msg 13552, Level 16, State 1, Line 6
Drop table operation failed on table ‘SQL2017_DEMO.dbo.Demo’ because it is not a supported operation on system-versioned temporal tables.

Hope you find this post helpful !!!

Advertisement

Temporal Tables–Simple Guide to implement History Tables using SQL Server 2016/2017–Part 2–Accessing History data


In previous post, we saw how to create Temporal tables or enable System Versioning on an existing table

In this post, we will review how to access History data

Using below code, we will create simple Temporal table and inserted 5 records and querying both the Main and History table

CREATE TABLE dbo.Demo 
 (    
      DemoID int NOT NULL PRIMARY KEY CLUSTERED  IDENTITY 
    , DemoName varchar(50) NOT 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 (HISTORY_TABLE = dbo.DemoHistory)) 
 ;

INSERT INTO dbo.Demo (DemoName) VALUES ('Demo1') 
 INSERT INTO dbo.Demo (DemoName) VALUES ('Demo2') 
 INSERT INTO dbo.Demo (DemoName) VALUES ('Demo3') 
 INSERT INTO dbo.Demo (DemoName) VALUES ('Demo4') 
 INSERT INTO dbo.Demo (DemoName) VALUES ('Demo5')

SELECT DemoID, 
        DemoName, 
        SysStartTime, 
        SysEndTime FROM dbo.Demo

SELECT DemoID, 
        DemoName, 
        SysStartTime, 
        SysEndTime FROM dbo.DemoHistory

 

Output: Main table has 5 rows and and History has no data, because no changes were made yet to the data, Also if you notice the SysEndTime, all of them are set to 12/31/9999 23:59:59.9999999, which refer to them as current record

capture20171020104246809

Let us modify some data in 2 minute intervals

First Change – Update 1 row and delete 1 row

UPDATE dbo.Demo 
    SET DemoName='Demo11' 
    WHERE DemoID=1

DELETE FROM dbo.Demo WHERE DemoID=4

Output: Now we can see that Main table has 4 rows and History has 2 rows , the green highlighted is the record we updated as you can history table contains the previous version of record and also SysEndTime in History table indicates when it was updated

Similarly Red highlighted record in history is the deleted with Deleted time

capture20171020104303651

Second Update: Update 1 record and Delete 1 record

UPDATE dbo.Demo 
    SET DemoName='Demo12' 
    WHERE DemoID=2

DELETE FROM dbo.Demo WHERE DemoID=3

Output:

capture20171020121832704

Let us now review how we can access the History data

Method 1: AS OF

We can use FOR SYSTEM_TIME AS OF to get records in Demo as of the specific time, This will be helpful for scenarios when you want to see How much Inventory was in hand as of a particular date and time or What products were in hand as of particular date and time

In below example we are using 3 different time with 2 minute intervals

SELECT DemoID, 
       DemoName, 
       SysStartTime, 
        SysEndTime FROM dbo.Demo 
    FOR SYSTEM_TIME AS OF '2017-10-20 14:42:34' 
    ORDER BY DemoID

SELECT DemoID, 
       DemoName, 
       SysStartTime, 
       SysEndTime FROM dbo.Demo 
    FOR SYSTEM_TIME AS OF '2017-10-20 14:44:34' 
    ORDER BY DemoID

SELECT DemoID, 
       DemoName, 
        SysStartTime, 
       SysEndTime FROM dbo.Demo 
    FOR SYSTEM_TIME AS OF '2017-10-20 14:46:34' 
    ORDER BY DemoID

Output: As we can see in first output we are able to see all records as how it was inserted and in 2nd put, we can see 1st record was updated and Demo ID 4 record is missing and in output 3 23 can seem Demo ID 1 and 2 are updated and 3 and 4 are deleted

capture20171020122217154

Method 2: FROM…TO and  BETWEEN…AND option

We can use FROM…TO and BETWEEN…AND option to get records changed between 2 specified date times

SELECT DemoID, 
       DemoName, 
       SysStartTime, 
       SysEndTime 
    FROM dbo.Demo 
    FOR SYSTEM_TIME FROM '2017-10-20 14:42:33' TO '2017-10-20 14:46:55' 
    ORDER BY DemoID, SysStartTime

SELECT DemoID, 
        DemoName, 
       SysStartTime, 
       SysEndTime 
    FROM dbo.Demo 
    FOR SYSTEM_TIME BETWEEN '2017-10-20 14:42:33' AND '2017-10-20 14:46:55' 
    ORDER BY DemoID, SysStartTime

 

Output: In below output you can see all changes made between the specified time intervals, but if you notice it, its providing us both version of the records, so based on your application need, you will need to use this or else, it might provide more records for display than you need

capture20171020123046024

Method 3: CONTAINED IN

When we use CONTAINED IN option, it provides data from history table only for the specified datetime(s)

SELECT DemoID, 
        DemoName, 
        SysStartTime, 
       SysEndTime 
    FROM dbo.Demo 
    FOR SYSTEM_TIME CONTAINED IN ('2017-10-20 14:42:33', '2017-10-20 14:45:56') 
    ORDER BY DemoID, SysStartTime

 

Output: As we can see the below output doesn’t contain the current version of record or other records from Main table

capture20171020123430862

Method 4: ALL

When we use ALL option, it provides data from both Main and History table for all the changes made so far

SELECT DemoID, 
        DemoName, 
        SysStartTime, 
       SysEndTime FROM dbo.Demo 
    FOR SYSTEM_TIME ALL 
    ORDER BY DemoID, SysStartTime

Output

We can see all records from main and history table combined, Please be cautious using this option when running without Filter criteria for larger tables

capture20171020123659353

We can create Views using Temporal Tables and those views supports these clauses as well

Hope you find this post helpful !!!

Temporal Tables–Simple Guide to implement History Tables using SQL Server 2016/2017


Temporal Tables is a new feature introduced in SQL Server 2016, which makes database/application developers life easy to implement History feature in their application without having to write Triggers or any extra logic in stored procedures

Method 1: Creating Temporal Tables for New Table without explicitly specifying History table name

Please add these 3 columns to your table definition and use WITH (SYSTEM_VERSIONING = ON)

CREATE TABLE dbo.Demo
(
DemoID int NOT NULL PRIMARY KEY CLUSTERED
, DemoName varchar(50) NOT 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);

In below screenshot, you can see that Demo table is created with History table, but History table name is generated by SQL Server itself, the default naming conversion is dbo.MSSQL_TemporalHistoryFor<OBJECTID of Table>

capture20171019184815324

Method 2: Creating Temporal Tables for New Table with explicit History table name

CREATE TABLE dbo.Demo2
(
DemoID int NOT NULL PRIMARY KEY CLUSTERED
, DemoName varchar(50) NOT 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 (HISTORY_TABLE = dbo.Demo2History));

In the below screenshot, you can see the dbo.Demo2 table is created with History table name

capture20171019193451893

Method 3: Altering an existing table to implement Temporal table

The below table dbo.Demo3 already exists

capture20171019194304832

ALTER TABLE dbo.Demo3 ADD SysStartTime datetime2 GENERATED ALWAYS AS ROW START NOT NULL
, SysEndTime datetime2 GENERATED ALWAYS AS ROW END NOT NULL
, PERIOD FOR SYSTEM_TIME (SysStartTime,SysEndTime)

ALTER TABLE dbo.Demo3
SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.Demo3History))

In below screenshot you can see Demo3 table is modified to include

capture20171019194022657

In next post, we will see how INSERT/UPDATE/DELETE operation ran on main table generates History data and how we can access it

Hope you find this post helpful !!!

%d bloggers like this: