{"id":954,"date":"2025-01-10T00:36:16","date_gmt":"2025-01-10T00:36:16","guid":{"rendered":"https:\/\/turtleflyblog.com\/?p=954"},"modified":"2025-01-10T00:36:19","modified_gmt":"2025-01-10T00:36:19","slug":"sql-server-temporal-table","status":"publish","type":"post","link":"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/","title":{"rendered":"SQL SERVER Temporal Table"},"content":{"rendered":"\n

Temporal Table was added in SQL SERVER 2016. The primary feature of temporal table is to record a table\u2019s history data. Temporal table will record every data that is added, updated or deleted in a table in any movement. The new version of EntityFramework Core also has some Temporal Table functions. Temporal Table primary has these three functions.<\/p>\n\n\n\n

Auditing: <\/strong>For certain industries, such as financial or pharmactural institutions, historical records can be tracked to see if any data has been added or deleted.<\/strong><\/p>\n\n\n\n

History Data Analysis<\/strong>: It is possible to analyze the historical records of a company’s products to determine sales performance, especially during specific time periods. This is also useful for analyzing stock market trends.<\/p>\n\n\n\n

Data recovery<\/strong>: For example, in a bank, if something goes wrong due to misuse, data can be recovered by observing and tracking historical records.<\/p>\n\n\n\n

Example:<\/strong><\/p>\n\n\n\n

Build a table<\/strong><\/p>\n\n\n\n

Build a table with its temporal table. Table schema is shown below\u3002The table\u2019s name is BookInventory. The table has itstemporal table as dbo.BookInventoryHistory\u3002BookInventoryHistory is System-Versioned\u3002”System-Versioned” means that SQL Server can automatically generate and maintain a Historical Table.<\/p>\n\n\n\n

\"\"<\/figure>\n\n\n\n

GENERATED ALWAYS AS ROW START:<\/strong> valid start date for the data row<\/p>\n\n\n\n

GENERATED ALWAYS AS ROW END:<\/strong> end date for the data row<\/p>\n\n\n\n

 PERIOD FOR SYSTEM_TIME :<\/strong>indicate the valid start and end time<\/p>\n\n\n\n

SYSTEM_VERSIONING = ON<\/strong> (HISTORY_TABLE = dbo.BookInventoryHistory<\/strong>):<\/p>\n\n\n\n

Enabled activating Temporal Table, dbo.BookInventoryHistory is the temporal table of BookInventoryHistory.<\/p>\n\n\n\n

Add Data<\/strong><\/p>\n\n\n\n

BookInventory Inserts two data(shown below)<\/p>\n\n\n\n

\"\"<\/figure>\n\n\n\n

dbo.BookInventory<\/p>\n\n\n\n

\"\"<\/figure>\n\n\n\n

dbo.BookInventoryHistory<\/p>\n\n\n\n

\"\"<\/figure>\n\n\n\n

We will oberserve BookInventory table and its temporal table(BookInventoryHistory) after these two data are added. BookInventory has these two data, but BookInventory hasn\u2019t yet. This is because the first step is \u2018Insert\u2019, we have to wait the next step such as \u2018Update\u2019, the first inserted data will then be stored in BookInventoryHistory(Temporal table).<\/p>\n\n\n\n

Update Data-Step 1<\/strong><\/p>\n\n\n\n

\"\"<\/figure>\n\n\n\n

dbo.BookInventory<\/p>\n\n\n\n

\"\"<\/figure>\n\n\n\n

dbo.BookInventoryHistory<\/p>\n\n\n\n

\"\"<\/figure>\n\n\n\n

After updated these two data, the table BookInventory has these two modified data. Then we see BookInventoryHistory has these two unmodified data. SysStartTime is the date the data has originated generated, SysEndTime is the updated(modified) date.<\/p>\n\n\n\n

Update Data \u2013 Step 2<\/strong><\/p>\n\n\n\n

\"\"<\/figure>\n\n\n\n
\"\"<\/figure>\n\n\n\n

dbo.BookInventory<\/p>\n\n\n\n

\"\"<\/figure>\n\n\n\n

dbo.BookInventoryHistory<\/p>\n\n\n\n

\"\"<\/figure>\n\n\n\n

We then check the outcome of Update data. This time we update two data. The temporal table BookInventoryHistory shall have four data(last updated data and also this updated data). We query the table BookInventoryHistory table, the result is as expected. BookInventoryHistory can track every updated data, as well as its modified time.<\/p>\n\n\n\n

Delete Data<\/strong><\/p>\n\n\n\n

\"\"<\/figure>\n\n\n\n

dbo.BookInventory<\/p>\n\n\n\n

\"\"<\/figure>\n\n\n\n

dbo.BookInventoryHistory<\/p>\n\n\n\n

\"\"<\/figure>\n\n\n\n

This time we delete one data form the table to see how the temporal table behaves. After deleting a data, BookInventory only has one data remained(another data is deleted). We then observe BookInventoryHistory and see there are five data stored its data(four updated data and one deleted data).<\/p>\n\n\n\n

Track Data<\/strong><\/p>\n\n\n\n

\"\"<\/figure>\n\n\n\n

Dbo.BookInventory<\/p>\n\n\n\n

\"\"<\/figure>\n\n\n\n

The valid active data at the time ‘2024-09-02 02:23:57.3447172’<\/p>\n\n\n\n

Conclusion<\/strong><\/p>\n\n\n\n

Temporal Table has its constraints such as constraint is not available in temporal table. Temporal table also needs additional memory, and it is complicate to increase performance for browsing temporal table. However, it is very useful in tracking historical modified data. Prior Sql Server 2016, we have to use Trigger or Store Procedure to track Historical data. I will introduce how to use Temporal Table in EntityFramework Core.<\/p>\n\n\n\n

References<\/strong><\/p>\n\n\n\n

Microsoft Docs, “<\/strong>Temporal Tables<\/strong><\/a>“<\/strong><\/p>\n\n\n\n

Pluralsight Couse <\/strong>Querying Data in EF Core<\/strong><\/a>– <\/strong>Temporal Tables<\/strong><\/a><\/p>\n\n\n\n

The importance of traceability of changes, https:\/\/itequia.com\/en\/table-versioning-in-sql-server-what-is-it-and-how-does-it-work\/<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"

Temporal Table was added in SQL SERVER 2016. The primary feature of temporal table is to record a table\u2019s history data. Temporal table will record every data that is added, updated or deleted in a table in any movement. The new version of EntityFramework Core also has some Temporal Table functions. Temporal Table primary has […]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[29],"tags":[],"class_list":["post-954","post","type-post","status-publish","format-standard","hentry","category-database"],"yoast_head":"\nSQL SERVER Temporal Table - Who said turtle cannot fly<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"SQL SERVER Temporal Table - Who said turtle cannot fly\" \/>\n<meta property=\"og:description\" content=\"Temporal Table was added in SQL SERVER 2016. The primary feature of temporal table is to record a table\u2019s history data. Temporal table will record every data that is added, updated or deleted in a table in any movement. The new version of EntityFramework Core also has some Temporal Table functions. Temporal Table primary has […]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/\" \/>\n<meta property=\"og:site_name\" content=\"Who said turtle cannot fly\" \/>\n<meta property=\"article:published_time\" content=\"2025-01-10T00:36:16+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-01-10T00:36:19+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/turtleflyblog.com\/wp-content\/uploads\/2025\/01\/image.png\" \/>\n<meta name=\"author\" content=\"Joseph\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Joseph\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/\",\"url\":\"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/\",\"name\":\"SQL SERVER Temporal Table - Who said turtle cannot fly\",\"isPartOf\":{\"@id\":\"https:\/\/turtleflyblog.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/turtleflyblog.com\/wp-content\/uploads\/2025\/01\/image.png\",\"datePublished\":\"2025-01-10T00:36:16+00:00\",\"dateModified\":\"2025-01-10T00:36:19+00:00\",\"author\":{\"@id\":\"https:\/\/turtleflyblog.com\/#\/schema\/person\/130c2e1bdce4a8ba27bfe14c65988172\"},\"breadcrumb\":{\"@id\":\"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/#breadcrumb\"},\"inLanguage\":\"en-AU\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-AU\",\"@id\":\"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/#primaryimage\",\"url\":\"https:\/\/i0.wp.com\/turtleflyblog.com\/wp-content\/uploads\/2025\/01\/image.png?fit=864%2C459&ssl=1\",\"contentUrl\":\"https:\/\/i0.wp.com\/turtleflyblog.com\/wp-content\/uploads\/2025\/01\/image.png?fit=864%2C459&ssl=1\",\"width\":864,\"height\":459},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/turtleflyblog.com\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"SQL SERVER Temporal Table\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/turtleflyblog.com\/#website\",\"url\":\"https:\/\/turtleflyblog.com\/\",\"name\":\"Who said turtle cannot fly\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/turtleflyblog.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-AU\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/turtleflyblog.com\/#\/schema\/person\/130c2e1bdce4a8ba27bfe14c65988172\",\"name\":\"Joseph\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-AU\",\"@id\":\"https:\/\/turtleflyblog.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/539caa7bc4af75cd4ab82fc8d51935da?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/539caa7bc4af75cd4ab82fc8d51935da?s=96&d=mm&r=g\",\"caption\":\"Joseph\"},\"sameAs\":[\"https:\/\/turtleflyblog.com\/\/\"],\"url\":\"https:\/\/turtleflyblog.com\/author\/joseph\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"SQL SERVER Temporal Table - Who said turtle cannot fly","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/","og_locale":"en_US","og_type":"article","og_title":"SQL SERVER Temporal Table - Who said turtle cannot fly","og_description":"Temporal Table was added in SQL SERVER 2016. The primary feature of temporal table is to record a table\u2019s history data. Temporal table will record every data that is added, updated or deleted in a table in any movement. The new version of EntityFramework Core also has some Temporal Table functions. Temporal Table primary has […]","og_url":"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/","og_site_name":"Who said turtle cannot fly","article_published_time":"2025-01-10T00:36:16+00:00","article_modified_time":"2025-01-10T00:36:19+00:00","og_image":[{"url":"https:\/\/turtleflyblog.com\/wp-content\/uploads\/2025\/01\/image.png","type":"","width":"","height":""}],"author":"Joseph","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Joseph","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/","url":"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/","name":"SQL SERVER Temporal Table - Who said turtle cannot fly","isPartOf":{"@id":"https:\/\/turtleflyblog.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/#primaryimage"},"image":{"@id":"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/#primaryimage"},"thumbnailUrl":"https:\/\/turtleflyblog.com\/wp-content\/uploads\/2025\/01\/image.png","datePublished":"2025-01-10T00:36:16+00:00","dateModified":"2025-01-10T00:36:19+00:00","author":{"@id":"https:\/\/turtleflyblog.com\/#\/schema\/person\/130c2e1bdce4a8ba27bfe14c65988172"},"breadcrumb":{"@id":"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/#breadcrumb"},"inLanguage":"en-AU","potentialAction":[{"@type":"ReadAction","target":["https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/"]}]},{"@type":"ImageObject","inLanguage":"en-AU","@id":"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/#primaryimage","url":"https:\/\/i0.wp.com\/turtleflyblog.com\/wp-content\/uploads\/2025\/01\/image.png?fit=864%2C459&ssl=1","contentUrl":"https:\/\/i0.wp.com\/turtleflyblog.com\/wp-content\/uploads\/2025\/01\/image.png?fit=864%2C459&ssl=1","width":864,"height":459},{"@type":"BreadcrumbList","@id":"https:\/\/turtleflyblog.com\/en\/2025\/01\/10\/sql-server-temporal-table\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/turtleflyblog.com\/en\/"},{"@type":"ListItem","position":2,"name":"SQL SERVER Temporal Table"}]},{"@type":"WebSite","@id":"https:\/\/turtleflyblog.com\/#website","url":"https:\/\/turtleflyblog.com\/","name":"Who said turtle cannot fly","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/turtleflyblog.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-AU"},{"@type":"Person","@id":"https:\/\/turtleflyblog.com\/#\/schema\/person\/130c2e1bdce4a8ba27bfe14c65988172","name":"Joseph","image":{"@type":"ImageObject","inLanguage":"en-AU","@id":"https:\/\/turtleflyblog.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/539caa7bc4af75cd4ab82fc8d51935da?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/539caa7bc4af75cd4ab82fc8d51935da?s=96&d=mm&r=g","caption":"Joseph"},"sameAs":["https:\/\/turtleflyblog.com\/\/"],"url":"https:\/\/turtleflyblog.com\/author\/joseph\/"}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/turtleflyblog.com\/wp-json\/wp\/v2\/posts\/954","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/turtleflyblog.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/turtleflyblog.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/turtleflyblog.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/turtleflyblog.com\/wp-json\/wp\/v2\/comments?post=954"}],"version-history":[{"count":1,"href":"https:\/\/turtleflyblog.com\/wp-json\/wp\/v2\/posts\/954\/revisions"}],"predecessor-version":[{"id":973,"href":"https:\/\/turtleflyblog.com\/wp-json\/wp\/v2\/posts\/954\/revisions\/973"}],"wp:attachment":[{"href":"https:\/\/turtleflyblog.com\/wp-json\/wp\/v2\/media?parent=954"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/turtleflyblog.com\/wp-json\/wp\/v2\/categories?post=954"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/turtleflyblog.com\/wp-json\/wp\/v2\/tags?post=954"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}