Converting an Existing SQL Server Temporal Table
In my previous article on SQL Server Temporal Tables I showed how to create a Temporal Table in a SQL Server database and do time-based querying but what if you have an existing table loaded with data? Sure, creating a new table and migrating it in can work but an easier solution is to just add the history table and system versioning to an existing table.
We will start with our example table, it’s a fairly simple for simplicity but I have made the conversion on much larger and complex tables.
Part 1 – Introduction to SQL Server Temporal Tables
Part 2 – Converting an Existing SQL Server Temporal Table
Part 3 – SQL Server Temporal Tables Advanced Query Strategies
CREATE TABLE [dbo].[ApplicationUser]
(
[UserId] nvarchar(20) NOT NULL,
[FirstName] nvarchar(100) NOT NULL,
[LastName] nvarchar(100) NOT NULL,
[JobTitle] nvarchar(100) NOT NULL,
[LastUpdatedBy] nvarchar(20) NOT NULL,
CONSTRAINT [PK_ApplicationUser] PRIMARY KEY CLUSTERED ([UserId] ASC),
);
SELECT * FROM [ApplicationUser]
For our example table an alter script looks like this:
ALTER TABLE [dbo].[ApplicationUser] ADD
[ValidFrom] datetime2 GENERATED ALWAYS AS ROW START NOT NULL DEFAULT SYSUTCDATETIME(),
[ValidTo] datetime2 GENERATED ALWAYS AS ROW END NOT NULL DEFAULT CAST('9999-12-31 23:59:59.9999999' AS datetime2),
PERIOD FOR SYSTEM_TIME ([ValidFrom],[ValidTo]);
ALTER TABLE [dbo].[ApplicationUser]
SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[ApplicationUserHistory]));
GO
CREATE TABLE [dbo].[ApplicationUser]
(
[UserId] nvarchar(20) NOT NULL,
[FirstName] nvarchar(100) NOT NULL,
[LastName] nvarchar(100) NOT NULL,
[JobTitle] nvarchar(100) NOT NULL,
[LastUpdatedBy] nvarchar(20) NOT NULL,
CONSTRAINT [PK_ApplicationUser] PRIMARY KEY CLUSTERED ([UserId] ASC),
);
GO
CREATE TABLE [dbo].[ApplicationUserHistory]
(
[UserId] nvarchar(20) NOT NULL,
[FirstName] nvarchar(100) NOT NULL,
[LastName] nvarchar(100) NOT NULL,
[JobTitle] nvarchar(100) NOT NULL,
[LastUpdatedBy] nvarchar(20) NOT NULL,
[ValidFrom] datetime2 NOT NULL,
[ValidTo] datetime2 NOT NULL,
);
GO
INSERT INTO ApplicationUser(UserId, FirstName, LastName, JobTitle, LastUpdatedBy) VALUES('U001','John','Doe','Supervisor','Frank')
INSERT INTO ApplicationUser(UserId, FirstName, LastName, JobTitle, LastUpdatedBy) VALUES('U002','Michael','Scott','Technician','John')
INSERT INTO ApplicationUser(UserId, FirstName, LastName, JobTitle, LastUpdatedBy) VALUES('U003','Betty','White','HR','Mary')
INSERT INTO ApplicationUser(UserId, FirstName, LastName, JobTitle, LastUpdatedBy) VALUES('U004','Mary','Evans','Supervisor','Michael')
INSERT INTO ApplicationUser(UserId, FirstName, LastName, JobTitle, LastUpdatedBy) VALUES('U005','James','Smith','Technician','Betty')
INSERT INTO [ApplicationUserHistory](UserId, FirstName, LastName, JobTitle, LastUpdatedBy, ValidFrom, ValidTo) VALUES('U001','John','Doe','Supervisor','Frank', '2022-11-01 23:13:01.8318438', '2022-11-02 23:13:01.8318438')
INSERT INTO [ApplicationUserHistory](UserId, FirstName, LastName, JobTitle, LastUpdatedBy, ValidFrom, ValidTo) VALUES('U002','Michael','Scott','Technician','John', '2022-11-01 22:13:01.8318438', '2022-11-02 23:13:01.8318438')
INSERT INTO [ApplicationUserHistory](UserId, FirstName, LastName, JobTitle, LastUpdatedBy, ValidFrom, ValidTo) VALUES('U003','Betty','White','HR','Mary', '2022-11-01 12:13:01.8318438', '2022-11-02 23:13:01.8318438')
INSERT INTO [ApplicationUserHistory](UserId, FirstName, LastName, JobTitle, LastUpdatedBy, ValidFrom, ValidTo) VALUES('U004','Mary','Evans','Supervisor','Michael', '2022-11-01 14:13:01.8318438', '2022-11-02 23:13:01.8318438')
INSERT INTO [ApplicationUserHistory](UserId, FirstName, LastName, JobTitle, LastUpdatedBy, ValidFrom, ValidTo) VALUES('U005','James','Smith','Technician','Betty', '2022-11-01 10:13:01.8318438', '2022-11-02 23:13:01.8318438')
ALTER TABLE [dbo].[ApplicationUser] ADD
[ValidFrom] datetime2 GENERATED ALWAYS AS ROW START NOT NULL DEFAULT SYSUTCDATETIME(),
[ValidTo] datetime2 GENERATED ALWAYS AS ROW END NOT NULL DEFAULT CAST('9999-12-31 23:59:59.9999999' AS datetime2),
PERIOD FOR SYSTEM_TIME ([ValidFrom],[ValidTo]);
ALTER TABLE [dbo].[ApplicationUser]
SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[ApplicationUserHistory]));
GO
Conclusion
You are now equipped to use temporal tables on new or existing tables and have a trick up your sleeve if you are asked to add change history to a table of data.
Part 1 – Introduction to SQL Server Temporal Tables
Part 2 – Converting an Existing SQL Server Temporal Table
Part 3 – SQL Server Temporal Tables Advanced Query Strategies
About Intertech
Intertech is a Software Development Consulting Firm that provides single and multiple turnkey software development teams, available on your schedule and configured to achieve success as defined by your requirements independently or in co-development with your team. Intertech teams combine proven full-stack, DevOps, Agile-experienced lead consultants with Delivery Management, User Experience, Software Development, and QA experts in Business Process Automation (BPA), Microservices, Client- and Server-Side Web Frameworks of multiple technologies, Custom Portal and Dashboard development, Cloud Integration and Migration (Azure and AWS), and so much more. Each Intertech employee leads with the soft skills necessary to explain complex concepts to stakeholders and team members alike and makes your business more efficient, your data more valuable, and your team better. In addition, Intertech is a trusted partner of more than 4000 satisfied customers and has a 99.70% “would recommend” rating.