임시 테이블Temporal Tables

이 항목은 다음에 적용됩니다. 예SQL Server(2016부터)예Azure SQL Database아니요Azure SQL Data Warehouse아니요병렬 데이터 웨어하우스 THIS TOPIC APPLIES TO: yesSQL Server (starting with 2016)yesAzure SQL DatabasenoAzure SQL Data Warehouse noParallel Data Warehouse

SQL Server 2016에는 시스템 버전 temporal 테이블에 대한 지원이 데이터베이스 기능으로 도입되었습니다. 이 기능은 현재 시점에 적절한 데이터에 대한 정보만 제공하는 것이 아니라 임의 시점에 테이블에 저장된 데이터에 대한 정보를 제공하는 것을 기본적으로 지원합니다.SQL Server 2016 introduced support for system-versioned temporal tables as a database feature that brings built-in support for providing information about data stored in the table at any point in time rather than only the data that is correct at the current moment in time. 임시 테이블은 ANSI SQL 2011에서 도입된 데이터베이스 기능입니다.Temporal is a database feature that was introduced in ANSI SQL 2011.

빠른 시작Quick Start

시스템 버전 임시 테이블이란?What is a system-versioned temporal table?

시스템 버전 임시 테이블은 데이터 변경 내용의 전체 기록을 유지하고 간편한 지정 시간 분석을 허용하도록 설계된 사용자 테이블의 종류입니다.A system-versioned temporal table is a type of user table designed to keep a full history of data changes and allow easy point in time analysis. 이 유형의 임시 테이블은 각 행의 유효 기간이 시스템(예: 데이터베이스 엔진)에 의해 관리되기 때문에 시스템 버전 임시 테이블이라고 합니다.This type of temporal table is referred to as a system-versioned temporal table because the period of validity for each row is managed by the system (i.e. database engine).

모든 임시 테이블에는 명시적으로 정의된 두 개의 열이 있으며, 각 열의 데이터 형식은 datetime2 입니다.Every temporal table has two explicitly defined columns, each with a datetime2 data type. 이러한 열을 기간 열이라고 합니다.These columns are referred to as period columns. 이러한 기간 열은 행이 수정될 때마다 시스템에서 각 행의 유효 기간을 기록하는 데에만 사용됩니다.These period columns are used exclusively by the system to record period of validity for each row whenever a row is modified.

이러한 기간 열 외에도 임시 테이블은 미러된 스키마를 사용하는 다른 테이블에 대한 참조를 포함합니다.In addition to these period columns, a temporal table also contains a reference to another table with a mirrored schema. 시스템에서는 이 테이블을 사용하여 임시 테이블의 행이 업데이트되거나 삭제될 때마다 이전 버전의 행을 자동으로 저장합니다.The system uses this table to automatically store the previous version of the row each time a row in the temporal table gets updated or deleted. 이 추가 테이블을 기록 테이블이라고 하며, 현재(실제) 행 버전을 저장하는 주 테이블을 현재 테이블 또는 임시 테이블이라고 합니다.This additional table is referred to as the history table, while the main table that stores current (actual) row versions is referred to as the current table or simply as the temporal table. 임시 테이블을 만드는 동안 사용자가 기존 기록 테이블(스키마를 준수해야 함)를 지정하거나 시스템에서 기본 기록 테이블을 만들도록 할 수 있습니다.During temporal table creation users can specify existing history table (must be schema compliant) or let system create default history table.

임시 테이블을 사용하는 이유Why temporal?

실제 데이터 원본은 동적이며, 비즈니스 의사 결정은 분석가가 데이터 진화에서 얻을 수 있는 통찰력에 의존하는 경우가 많습니다.Real data sources are dynamic and more often than not business decisions rely on insights that analysts can get from data evolution. 임시 테이블에 대한 사용 사례는 다음과 같습니다.Use cases for temporal tables include:

  • 모든 데이터 변경 내용을 감사하고 필요한 경우 데이터 범죄 분석 수행Auditing all data changes and performing data forensics when necessary

  • 과거 시점을 기준으로 데이터 상태 재구성Reconstructing state of the data as of any time in the past

  • 시간에 따른 추세 계산Calculating trends over time

  • 의사 결정 지원 응용 프로그램에 대한 느린 변경 차원 유지 관리Maintaining a slowly changing dimension for decision support applications

  • 실수로 인한 데이터 변경 및 응용 프로그램 오류로부터 복구Recovering from accidental data changes and application errors

임시 테이블의 작동 방식How does temporal work?

테이블에 대한 시스템 버전은 현재 테이블과 기록 테이블의 테이블 쌍으로 구현됩니다.System-versioning for a table is implemented as a pair of tables, a current table and a history table. 이러한 각 테이블 내에서 다음 두 개의 추가 datetime2 열은 각 행의 유효 기간을 정의하는 데 사용됩니다.Within each of these tables, the following two additional datetime2 columns are used to define the period of validity for each row:

  • 기간 시작 열: 시스템에서 이 열의 행에 대한 시작 시간을 기록합니다(일반적으로 SysStartTime 열로 표시됨).Period start column: The system records the start time for the row in this column, typically denoted as the SysStartTime column.

  • 기간 종료 열: 시스템에서 이 열의 행에 대한 종료 시간을 기록합니다(일반적으로 SysEndTime 열로 표시됨).Period end column: The system records the end time for the row in this column, typically denoted at the SysEndTime column.

    현재 테이블에는 각 행에 대한 현재 값이 포함됩니다.The current table contains the current value for each row. 기록 테이블에는 각 행에 대한 각각의 이전 값(있는 경우)과 유효 기간의 시작 시간 및 종료 시간이 포함됩니다.The history table contains each previous value for each row, if any, and the start time and end time for the period for which it was valid.

    Temporal-HowWorksTemporal-HowWorks

    다음의 간단한 예제에서는 가상 HR 데이터베이스에서 직원 정보를 사용하는 시나리오를 보여 줍니다.The following simple example illustrates a scenario with Employee information in hypothetical HR database:

CREATE TABLE dbo.Employee   
(    
  [EmployeeID] int NOT NULL PRIMARY KEY CLUSTERED   
  , [Name] nvarchar(100) NOT NULL  
  , [Position] varchar(100) NOT NULL   
  , [Department] varchar(100) NOT NULL  
  , [Address] nvarchar(1024) NOT NULL  
  , [AnnualSalary] decimal (10,2) NOT NULL  
  , [ValidFrom] datetime2 (2) GENERATED ALWAYS AS ROW START  
  , [ValidTo] datetime2 (2) GENERATED ALWAYS AS ROW END  
  , PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)  
 )    
 WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.EmployeeHistory));  

INSERTS: INSERT에서는 시스템에서 시스템 클록을 기준으로 SysStartTime 열의 값을 현재 트랜잭션의 시작 시간(UTC 표준 시간대)으로 설정하고, SysEndTime 열의 값을 최대값 9999-12-31에 할당합니다.INSERTS: On an INSERT, the system sets the value for the SysStartTime column to the begin time of the current transaction (in the UTC time zone) based on the system clock and assigns the value for the SysEndTime column to the maximum value of 9999-12-31. 그러면 행이 열린 것으로 표시됩니다.This marks the row as open.

UPDATES: UPDATE에서는 시스템에서 기록 테이블에 있는 행의 이전 값을 저장하고, 시스템 클록을 기준으로 SysEndTime 열의 값을 현재 트랜잭션의 시작 시간(UTC 표준 시간대)으로 설정합니다.UPDATES: On an UPDATE, the system stores the previous value of the row in the history table and sets the value for the SysEndTime column to the begin time of the current transaction (in the UTC time zone) based on the system clock. 그러면 행이 닫힌 것으로 표시되고 행이 유효 상태로 유지된 기간이 기록됩니다.This marks the row as closed, with a period recorded for which the row was valid. 현재 테이블에서는 행이 새 값으로 업데이트되고 시스템에서 시스템 클록을 기준으로 SysStartTime 열의 값을 트랜잭션의 시작 시간(UTC 표준 시간대)으로 설정합니다.In the current table, the row is updated with its new value and the system sets the value for the SysStartTime column to the begin time for the transaction (in the UTC time zone) based on the system clock. 현재 테이블에서 SysEndTime 열에 대해 업데이트된 행의 값은 최대값 9999-12-31로 그대로 유지됩니다.The value for the updated row in the current table for the SysEndTime column remains the maximum value of 9999-12-31.

DELETES: DELETE에서는 시스템에서 기록 테이블에 있는 행의 이전 값을 저장하고, 시스템 클록을 기준으로 SysEndTime 열의 값을 현재 트랜잭션의 시작 시간(UTC 표준 시간대)으로 설정합니다.DELETES: On a DELETE, the system stores the previous value of the row in the history table and sets the value for the SysEndTime column to the begin time of the current transaction (in the UTC time zone) based on the system clock. 그러면 행이 닫힌 것으로 표시되고 이전 행이 유효 상태로 유지된 기간이 기록됩니다.This marks the row as closed, with a period recorded for which the previous row was valid. 현재 테이블에서는 행이 제거됩니다.In the current table, the row is removed. 현재 테이블의 쿼리는 이 행을 반환하지 않습니다.Queries of the current table will not return this row. 기록 데이터를 처리하는 쿼리만 행이 닫힌 데이터를 반환합니다.Only queries that deal with history data return data for which a row is closed.

MERGE: MERGE에서는 작업이 MERGE문에 동작으로 지정된 항목에 따라 정확히 최대 세 개의 문( INSERT, UPDATE및/또는 DELETE )이 실행된 것처럼 동작합니다.MERGE: On a MERGE, the operation behaves exactly as if up to three statements (an INSERT, an UPDATE, and/or a DELETE) executed, depending on what is specified as actions in the MERGE statement.

중요

시스템 datetime2 열에 기록되는 시작 시간은 트랜잭션 자체의 시간을 기반으로 합니다.The times recorded in the system datetime2 columns are based on the begin time of the transaction itself. 예를 들어 단일 트랜잭션 내에 삽입된 모든 행은 SYSTEM_TIME 기간의 시작에 해당하는 열에 기록된 것과 UTC 시간이 동일합니다.For example, all rows inserted within a single transaction will have the same UTC time recorded in the column corresponding to the start of the SYSTEM_TIME period.

임시 데이터를 쿼리하는 방법How do I query temporal data?

SELECTFROM<table> 절은 5개의 임시 하위 절과 함께 새로운 FOR SYSTEM_TIME 절을 사용하여 현재 테이블 및 기록 테이블에서 데이터를 쿼리합니다.The SELECT statement FROM<table> clause has a new clause FOR SYSTEM_TIME with five temporal-specific sub-clauses to query data across the current and history tables. 이 새로운 SELECT 문의 구문은 단일 테이블에서 직접 지원되며, 여러 조인 및 여러 임시 테이블 위의 뷰를 통해 전파됩니다.This new SELECT statement syntax is supported directly on a single table, propagated through multiple joins, and through views on top of multiple temporal tables.

Temporal-QueryingTemporal-Querying

다음 쿼리는 2014년 1월 1일부터 2015년 1월 1일(포함) 사이에 활성 상태로 있었던 EmployeeID가 1000인 Employee 행에 대한 행 버전을 검색합니다.The following query searches for row versions for Employee row with EmployeeID = 1000 that were active at least for a portion of period between 1st January of 2014 and 1st January 2015 (including the upper boundary):

SELECT * FROM Employee   
    FOR SYSTEM_TIME    
        BETWEEN '2014-01-01 00:00:00.0000000' AND '2015-01-01 00:00:00.0000000'   
            WHERE EmployeeID = 1000 ORDER BY ValidFrom;  

참고

FOR SYSTEM_TIME은 유효 기간(SysStartTime = SysEndTime)이 0인 행을 필터링합니다.FOR SYSTEM_TIME filters out rows that have period of validity with zero duration (SysStartTime = SysEndTime).
이러한 행은 동일한 트랜잭션 내의 동일한 기본 키에서 여러 업데이트를 수행하는 경우에 생성됩니다.Those rows will be generated if you perform multiple updates on the same primary key within the same transaction.
이 경우 임시 쿼리는 트랜잭션 이전의 행 버전과 트랜잭션 이후에 실제가 된 행 버전만 표시합니다.In that case, temporal querying surfaces only row versions before the transactions and ones that became actual after the transactions.
이러한 행을 분석에 포함해야 하는 경우 기록 테이블을 직접 쿼리합니다.If you need to include those rows in the analysis, query the history table directly.

아래 표에서 행 한정의 SysStartTime 열은 쿼리 중인 테이블의 SysStartTime 열 값을 나타내고, SysEndTime 은 쿼리 중인 테이블의 SysEndTime 열 값을 나타냅니다.In the table below, SysStartTime in the Qualifying Rows column represents the value in the SysStartTime column in the table being queried and SysEndTime represents the value in the SysEndTime column in the table being queried. 전체 구문 및 예제는 FROM(Transact-SQL)시스템 버전 임시 테이블의 데이터 쿼리에서 지원되는 데이터베이스 기능입니다.For the full syntax and for examples, see FROM (Transact-SQL) and Querying Data in a System-Versioned Temporal Table.

Expression 행 한정Qualifying Rows DescriptionDescription
AS OF<date_time>AS OF<date_time> SysStartTime <= date_time AND SysEndTime > date_timeSysStartTime <= date_time AND SysEndTime > date_time 과거의 지정된 시간에 실제(현재)였던 값이 포함된 행이 있는 테이블을 반환합니다.Returns a table with a rows containing the values that were actual (current) at the specified point in time in the past. 내부적으로 임시 테이블과 기록 테이블 간에 합집합이 계산되며, 지정된 시간에 유효했던 행의 값을 반환하도록 결과가 <date_time> 매개 변수로 필터링됩니다.Internally, a union is performed between the temporal table and its history table and the results are filtered to return the values in the row that was valid at the point in time specified by the <date_time> parameter. 행 값은 system_start_time_column_name 값이 <date_time> 매개 변수 값보다 작거나 같고 system_end_time_column_name 값이 <date_time> 매개 변수 값보다 큰 경우에 유효한 것으로 간주됩니다.The value for a row is deemed valid if the system_start_time_column_name value is less than or equal to the <date_time> parameter value and the system_end_time_column_name value is greater than the <date_time> parameter value.
FROM<start_date_time>TO<end_date_time>FROM<start_date_time>TO<end_date_time> SysStartTime < end_date_time AND SysEndTime > start_date_timeSysStartTime < end_date_time AND SysEndTime > start_date_time FROM 인수에 대한 <start_date_time> 매개 변수 값 이전에 활성 상태가 시작되었든 아니면 TO 인수에 대한 <end_date_time> 매개 변수 값 이후에 활성 상태가 중단되었든 상관없이 지정된 시간 범위 내에 활성 상태였던 모든 행 버전의 값을 포함하는 테이블을 반환합니다.Returns a table with the values for all row versions that were active within the specified time range, regardless of whether they started being active before the <start_date_time> parameter value for the FROM argument or ceased being active after the <end_date_time> parameter value for the TO argument. 내부적으로 임시 테이블과 기록 테이블 간에 합집합이 계산되며, 지정된 시간 범위 중 임의의 시점에 활성 상태였던 모든 행 버전을 반환하도록 결과가 필터링됩니다.Internally, a union is performed between the temporal table and its history table and the results are filtered to return the values for all row versions that were active at any time during the time range specified. FROM 끝점으로 정의된 하위 경계에서 정확히 활동이 중지된 행은 포함되지 않고 TO 끝점으로 정의된 상위 경계에서 정확히 활성화된 레코드도 포함되지 않습니다.Rows that ceased being active exactly on the lower boundary defined by the FROM endpoint are not included and records that became active exactly on the upper boundary defined by the TO endpoint are not included also.
BETWEEN<start_date_time>AND<end_date_time>BETWEEN<start_date_time>AND<end_date_time> SysStartTime <= end_date_time AND SysEndTime > start_date_timeSysStartTime <= end_date_time AND SysEndTime > start_date_time <end_date_time> 끝점으로 정의된 상위 경계에서 활성화된 행이 반환되는 행 테이블에 포함된다는 점을 제외하고는 위의 FOR SYSTEM_TIME FROM <start_date_time>TO 설명과 같습니다.Same as above in the FOR SYSTEM_TIME FROM <start_date_time>TO <end_date_time> description, except the table of rows returned includes rows that became active on the upper boundary defined by the <end_date_time> endpoint.
CONTAINED IN (<start_date_time> , <end_date_time>)CONTAINED IN (<start_date_time> , <end_date_time>) SysStartTime >= start_date_time AND SysEndTime <= end_date_timeSysStartTime >= start_date_time AND SysEndTime <= end_date_time CONTAINED IN 인수에 대한 두 개의 datetime 값으로 정의된 지정된 시간 범위 내에 열리고 닫힌 모든 행 버전의 값을 포함하는 테이블을 반환합니다.Returns a table with the values for all row versions that were opened and closed within the specified time range defined by the two datetime values for the CONTAINED IN argument. 정확히 하위 경계에서 활성화되거나 상위 경계에서 활성 상태가 중단된 행이 포함됩니다.Rows that became active exactly on the lower boundary or ceased being active exactly on the upper boundary are included.
ALLALL 모든 행All rows 현재 테이블 및 기록 테이블에 속하는 행의 합집합을 반환합니다.Returns the union of rows that belong to the current and the history table.

참고

필요한 경우 이러한 기간 열을 명시적으로 참조하지 않는 쿼리에서 이러한 열이 반환되지 않도록 이러한 기간 열을 숨길 수 있습니다(SELECT * FROM<table> 시나리오).Optionally, you can choose to hide these period columns such that queries that do not explicitly reference these period columns do not return these columns (the SELECT * FROM<table> scenario). 숨겨진 열을 반환하려면 쿼리에서 숨겨진 열을 명시적으로 참조하기만 하면 됩니다.To return a hidden column, simply explicitly refer to the hidden column in the query. 마찬가지로 INSERTBULK INSERT 문은 이러한 새 기간 열이 존재하지 않은 것처럼 계속되며, 열 값이 자동으로 채워집니다.Similarly INSERT and BULK INSERT statements will continue as if these new period columns were not present (and the column values will be auto-populated). HIDDEN 절 사용에 대한 자세한 내용은 CREATE TABLE(Transact-SQL)ALTER TABLE(Transact-SQL)을 참조하세요.For details on using the HIDDEN clause, see CREATE TABLE (Transact-SQL) and ALTER TABLE (Transact-SQL).

이 문서가 도움이 되었나요?Did this Article Help You? 여러분의 의견을 환영합니다.We’re Listening

어떤 정보를 찾고 계세요? 정보를 찾으셨나요?What information are you looking for, and did you find it? 여러분의 의견은 문서의 내용을 개선하는 데 많은 도움이 됩니다.We’re listening to your feedback to improve the content. 의견이 있으면 sqlfeedback@microsoft.comPlease submit your comments to sqlfeedback@microsoft.com

참고 항목See Also

시스템 버전 관리 임시 테이블 시작 Getting Started with System-Versioned Temporal Tables
메모리 액세스에 최적화된 테이블을 포함한 시스템 버전 임시 테이블 System-Versioned Temporal Tables with Memory-Optimized Tables
임시 테이블 사용 시나리오 Temporal Table Usage Scenarios
임시 테이블 고려 사항 및 제한 사항 Temporal Table Considerations and Limitations
시스템 버전 관리된 임시 테이블에서 기록 데이터의 보존 관리 Manage Retention of Historical Data in System-Versioned Temporal Tables
임시 테이블을 사용하여 분할 Partitioning with Temporal Tables
임시 테이블 시스템 일관성 검사 Temporal Table System Consistency Checks
임시 테이블 보안 Temporal Table Security
임시 테이블 메타데이터 뷰 및 함수Temporal Table Metadata Views and Functions