Tabelle temporali
Si applica a: SQL Server 2016 (13.x) e versioni successive Database SQL di Azure Istanza gestita di SQL di Azure
Le tabelle temporali, note anche come tabelle temporali con controllo delle versioni del sistema, sono una funzionalità di database che offre un supporto predefinito per la gestione di informazioni sui dati archiviati nella tabella in qualsiasi momento anziché solo sui dati che risultano corretti nel momento attuale.
È possibile iniziare a usare tabelle temporali con controllo delle versioni di sistema ed esaminare gli scenari di utilizzo delle tabelle temporali.
Che cos'è una tabella temporale con controllo delle versioni di sistema?
Una tabella temporale con controllo delle versioni di sistema è un tipo di tabella utente progettato per mantenere una cronologia completa delle modifiche dei dati per semplificare l'analisi temporizzata. Questo tipo di tabella temporale è nota come tabella temporale con controllo delle versioni del sistema perché il sistema gestisce il periodo di validità per ogni riga (ossia il motore di database).
Ogni tabella temporale ha due colonne definite in modo esplicito, ciascuna con un tipo di dati datetime2 . Queste colonne sono note come colonne periodo. Le colonne periodo vengono usate esclusivamente dal sistema per registrare il periodo di validità per ciascuna riga ogni volta che una riga viene modificata. La tabella principale che archivia i dati correnti viene definita tabella corrente o semplicemente tabella temporale.
Oltre alle colonne periodo, una tabella temporale contiene anche un riferimento a un'altra tabella con schema con mirroring, definita tabella di cronologia. Il sistema usa la tabella di cronologia per archiviare automaticamente la versione precedente della riga ogni volta che una riga della tabella temporale viene aggiornata o eliminata. Durante la creazione di una tabella temporale è possibile specificare una tabella di cronologia esistente, che deve essere conforme allo schema, oppure consentire al sistema di creare una tabella di cronologia predefinita.
Perché temporale?
Le origini dati reali sono dinamiche e quasi sempre le decisioni aziendali si basano su approfondimenti che gli analisti ricavano dall'evoluzione dei dati. Alcuni casi d'uso delle tabelle temporali:
- Controllo di tutte le modifiche dei dati ed esecuzione di analisi forensi, se necessario
- Ricostruzione dello stato dei dati in qualsiasi momento trascorso
- Calcolo delle tendenze nel tempo
- Gestione di una dimensione a modifica lenta per le applicazioni di supporto decisionale
- Recupero da modifiche accidentali dei dati ed errori delle applicazioni
Come funziona una tabella temporale?
Il controllo delle versioni di sistema per una tabella viene implementato come una coppia di tabelle, una tabella corrente e una tabella di cronologia. All'interno di ogni tabella vengono usate due colonne datetime2 extra per definire il periodo di validità per ogni riga:
Colonna di inizio periodo: il sistema registra l'ora di inizio per la riga in questa colonna, in genere indicata come colonna
ValidFrom
.Colonna di fine periodo: il sistema registra l'ora di fine per la riga in questa colonna, in genere indicata come colonna
ValidTo
.
La tabella corrente contiene il valore corrente per ogni riga. La tabella di cronologia contiene ogni valore precedente (versione precedente) per ogni riga, se presente, e l'ora di inizio e di fine del relativo periodo di validità.
Lo script seguente illustra uno scenario con informazioni sui dipendenti:
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 GENERATED ALWAYS AS ROW START,
[ValidTo] DATETIME2 GENERATED ALWAYS AS ROW END,
PERIOD FOR SYSTEM_TIME(ValidFrom, ValidTo)
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.EmployeeHistory));
Per altre informazioni, vedere Creazione di una tabella temporale con controllo delle versioni di sistema.
Inserti: il sistema imposta il valore per la colonna
ValidFrom
sul momento di avvio della transazione corrente (fuso orario UTC) in base al clock di sistema e assegna come valore per la colonnaValidTo
il valore massimo9999-12-31
. In questo modo la riga viene contrassegnata come aperta.Aggiornamenti: il sistema archivia il valore precedente del record nella tabella di cronologia e imposta il valore per la colonna
ValidTo
sull'ora di inizio della transazione corrente (fuso orario UTC) in base al clock di sistema. In questo modo la riga viene contrassegnata come chiusa, con un periodo registrato in cui risultava valida. Nella tabella corrente la riga viene aggiornata con il nuovo valore e il sistema imposta il valore per la colonnaValidFrom
sul momento di avvio della transazione (fuso orario UTC) in base al clock di sistema. Il valore per la riga aggiornata nella tabella corrente per la colonnaValidTo
rimane il valore massimo di9999-12-31
.Eliminare: il sistema archivia il valore precedente del record nella tabella di cronologia e imposta il valore per la colonna
ValidTo
sul momento di avvio della transazione corrente (fuso orario UTC) in base al clock di sistema. In questo modo la riga viene contrassegnata come chiusa, con un periodo registrato in cui la riga precedente risultava valida. Nella tabella corrente la riga viene rimossa. Le query della tabella corrente non restituiscono questa riga. Solo le query che gestiscono i dati di cronologia restituiscono dati per i quali viene chiusa una riga.Unire: l'operazione si comporta esattamente come se venissero eseguite fino a tre istruzioni (
INSERT
,UPDATE
e/oDELETE
), in base alle azioni specificate nell'istruzioneMERGE
.
I tempi registrati nelle colonne datetime2 del sistema sono basati sull'ora di inizio della transazione stessa. Ad esempio, tutte le righe inserite all'interno di una singola transazione avranno lo stesso orario UTC registrato nella colonna corrispondente all'inizio del periodo SYSTEM_TIME
.
Quando si eseguono query di modifica dei dati in una tabella temporale, il motore di database aggiunge una riga alla tabella di cronologia anche se non viene modificato alcun valore di colonna.
Come si esegue una query sui dati temporali?
L'istruzione SELECT ... FROM <table>
ha una nuova clausola FOR SYSTEM_TIME
con cinque sottoclausole specifiche per i dati temporali per eseguire query sui dati nelle tabelle correnti e di cronologia. La nuova sintassi dell'istruzione SELECT
è supportata direttamente su una singola tabella, propagata attraverso diversi join e viste su più tabelle temporali.
Quando si esegue una query utilizzando la clausola FOR SYSTEM_TIME
con una delle cinque sottoclausole, vengono inclusi i dati storici della tabella temporale, come mostrato nell'immagine seguente.
La query seguente cerca con la condizione di filtro WHERE EmployeeID = 1000
le versioni di riga per un dipendente che erano attive almeno per una parte del periodo compreso tra il 1° gennaio 2021 e il 1° gennaio 2022, incluso il limite superiore:
SELECT * FROM Employee
FOR SYSTEM_TIME
BETWEEN '2021-01-01 00:00:00.0000000' AND '2022-01-01 00:00:00.0000000'
WHERE EmployeeID = 1000 ORDER BY ValidFrom;
FOR SYSTEM_TIME
esclude le righe che hanno un periodo di validità con durata pari a zero (ValidFrom = ValidTo
).
Tali righe vengono generate se si eseguono più aggiornamenti sulla stessa chiave primaria nell'ambito della stessa transazione. In tale caso l'esecuzione di query temporali restituisce solo le versioni di righe prima delle transazioni e le righe correnti dopo le transazioni.
Se è necessario includere le righe nell'analisi, eseguire la query direttamente nella tabella di cronologia.
Nella seguente tabella il valore ValidFrom
della colonna delle righe risultanti rappresenta il valore presente nella colonna ValidFrom
della tabella su cui si esegue la query e ValidTo
rappresenta il valore presente nella colonna ValidTo
della tabella su cui si esegue la query. Per la sintassi completa e per esempi, vedere FROM condizione più JOIN, APPLY, PIVOT e Query sui dati in una tabella temporale con controllo delle versioni di sistema.
Espressione | Righe risultanti | Nota |
---|---|---|
AS OF date_time |
ValidFrom <= date_time AND ValidTo > date_time |
Restituisce una tabella con una righe contenenti i valori che erano correnti in un momento specificato nel passato. Internamente, viene eseguita un'unione tra la tabella temporale e la relativa tabella di cronologia. I risultati vengono filtrati in modo da restituire i valori nella riga valida alla data e all'ora specificate nel parametro date_time. Il valore di una riga viene considerato valido se il valore system_start_time_column_name è minore o uguale al valore del parametro date_time e il valore system_end_time_column_name è maggiore del valore del parametro date_time. |
FROM start_date_time TO end_date_time |
ValidFrom < end_date_time AND ValidTo > start_date_time |
Restituisce una tabella con i valori per tutte le versioni di riga che erano attive nell'intervallo di tempo specificato, indipendentemente dal fatto che abbiano iniziato ad essere attive prima del valore del parametro start_date_time per l'argomento FROM o abbiano cessato di essere attive dopo il valore del parametro end_date_time per l'argomento TO . Internamente, viene eseguita un'unione tra la tabella temporale e la relativa tabella di cronologia. I risultati vengono filtrati in modo da restituire i valori per tutte le versioni di riga che erano attive in qualsiasi momento durante l'intervallo di tempo specificato. Le righe che non sono più state attive esattamente in corrispondenza del limite inferiore definito dall'endpoint FROM non sono incluse e le righe diventate attive esattamente in corrispondenza del limite superiore definito dall'endpoint TO non sono incluse. |
BETWEEN start_date_time AND end_date_time |
ValidFrom <= end_date_time AND ValidTo > start_date_time |
Come sopra nella descrizione FOR SYSTEM_TIME FROM start_date_time TO end_date_time, tranne che la tabella delle righe restituite include le righe che sono diventate attive sul limite superiore definito dall'end_date_time endpoint. |
CONTAINED IN (start_date_time, end_date_time) |
ValidFrom >= start_date_time AND ValidTo <= end_date_time |
Restituisce una tabella con i valori per tutte le versioni di riga che sono state aperte e chiuse nell'intervallo di tempo specificato, definito dai due valori di periodo per l'argomento CONTAINED IN . Sono incluse le righe diventate attive esattamente in corrispondenza del limite inferiore o che non sono più state attive esattamente in corrispondenza del limite superiore. |
ALL |
Tutte le righe | Restituisce l'unione di righe che appartengono alla tabella corrente e a quella di cronologia. |
Nascondere le colonne di periodo
È possibile scegliere di nascondere le colonne di periodo, in modo che le query che non fanno riferimento in modo esplicito a queste colonne non le restituiscano, ad esempio quando si esegue SELECT * FROM <table>
.
Per restituire una colonna nascosta, è necessario fare riferimento in modo esplicito alla colonna nella query. Allo stesso modo, le istruzioni INSERT
e BULK INSERT
continueranno come se le nuove colonne periodo non fossero presenti e i valori delle colonne vengono popolati automaticamente.
Per informazioni dettagliate sull'uso della clausola HIDDEN
, vedere CREATE TABLE e ALTER TABLE.
Esempi
ASP.NET: Si veda l’applicazione Web ASP.NET Core per informazioni su come creare un'applicazione temporale usando tabelle temporali.
Database di esempio AdventureWorks: scaricare il database AdventureWorks per SQL Server, che include funzionalità della tabella temporale.
Contenuto correlato
- Considerazioni e limitazioni delle tabelle temporali
- Gestire la conservazione dei dati storici nelle tabelle temporali con controllo delle versioni di sistema
- Partizioni con tabelle temporali
- Verifiche coerenza del sistema della tabella temporale
- Sicurezza di una tabella temporale
- Funzioni e viste per i metadati delle tabelle temporali
- Usare una tabella temporale con controllo delle versioni di sistema e ottimizzazione per la memoria
- Creare una tabella temporale con controllo delle versioni di sistema
- Modifica dei dati in una tabella temporale con controllo delle versioni di sistema
- Query sui dati in una tabella temporale con controllo delle versioni di sistema
- Introduzione alle tabelle temporali con controllo delle versioni di sistema
- Tabelle temporali con controllo delle versioni di sistema con tabelle ottimizzate per la memoria
- Informazioni introduttive sulle tabelle temporali nel database SQL di Azure e Istanza gestita di SQL di Azure