Interroger les données dans une table temporelle avec version gérée par le système
S’applique à : SQL Server 2016 (13.x) et versions ultérieures Base de données Azure SQL Azure SQL Managed Instance
Quand vous voulez obtenir l’état (réel) le plus récent des données d’une table temporelle, vous pouvez l’interroger exactement de la même façon que vous interrogez une table non temporelle. Si les colonnes PERIOD
ne sont pas masquées, leurs valeurs apparaissent dans une requête SELECT *
. Si vous avez spécifié des colonnes PERIOD
comme étant HIDDEN
, leurs valeurs n’apparaissent pas dans une requête SELECT *
. Quand les colonnes PERIOD
sont masquées, vous devez référencer spécifiquement les colonnes PERIOD
dans la clause SELECT
pour retourner les valeurs de ces colonnes.
Pour exécuter n’importe quel type d’analyse temporelle, utilisez la nouvelle clause FOR SYSTEM_TIME
avec quatre sous-clauses temporelles spécifiques pour d’interroger les données des tables actuelles et historiques. Pour plus d’informations sur ces clauses, consultez Tables temporelles et la clause FROM, plus JOIN, APPLY, PIVOT
AS OF <date_time>
FROM <start_date_time> TO <end_date_time>
BETWEEN <start_date_time> AND <end_date_time>
CONTAINED IN (<start_date_time>, <end_date_time>)
ALL
La clause FOR SYSTEM_TIME
peut être spécifiée de façon indépendante pour chaque table dans une requête. Elle peut être utilisée dans les expressions de table courantes, les fonctions table et les procédures stockées. Lors de l’utilisation d’un alias de table avec une table temporelle, la clause FOR SYSTEM_TIME
doit être placée entre le nom de la table temporelle et l’alias (consultez le deuxième exemple ci-dessous dans Interroger un point précis dans le temps en utilisant la sous-clause AS OF
).
Interroger un point précis dans le temps en utilisant la sous-clause AS OF
Utilisez la sous-clause AS OF
quand vous devez reconstruire l’état des données tel qu’il était à un point spécifique dans le temps. Vous pouvez reconstruire les données avec la précision de type datetime2 qui a été spécifiée dans les définitions des colonnes PERIOD
.
La sous-clause AS OF
peut être utilisée avec des constantes littérales ou des variables, afin de pouvoir spécifier dynamiquement la condition de temps. Les valeurs fournies sont interprétées en heure UTC.
Ce premier exemple retourne l’état de la table dbo.Department à partir (AS OF
) d’une date spécifique dans le passé.
-- State of entire table AS OF specific date in the past
SELECT [DeptID],
[DeptName],
[ValidFrom],
[ValidTo]
FROM [dbo].[Department]
FOR SYSTEM_TIME AS OF '2021-09-01 T10:00:00.7230011';
Ce second exemple compare les valeurs entre deux points dans le temps pour un sous-ensemble de lignes.
DECLARE @ADayAgo DATETIME2;
SET @ADayAgo = DATEADD(DAY, -1, SYSUTCDATETIME());
-- Comparison between two points in time for subset of rows
SELECT D_1_Ago.[DeptID],
D.[DeptID],
D_1_Ago.[DeptName],
D.[DeptName],
D_1_Ago.[ValidFrom],
D.[ValidFrom],
D_1_Ago.[ValidTo],
D.[ValidTo]
FROM [dbo].[Department]
FOR SYSTEM_TIME AS OF @ADayAgo AS D_1_Ago
INNER JOIN [Department] AS D
ON D_1_Ago.[DeptID] = [D].[DeptID]
AND D_1_Ago.[DeptID] BETWEEN 1 AND 5;
Utiliser des vues avec la sous-clause AS OF
dans des requêtes temporelles
Les vues sont utiles dans les scénarios nécessitant une analyse complexe à un point précis dans le temps. Un exemple courant est la création aujourd’hui d’un rapport d'entreprise s’appuyant sur les valeurs du mois précédent.
En règle générale, les clients utilisent un modèle de base de données normalisé qui implique de nombreuses tables avec des relations de clés étrangères. Connaître l’état des données de ce modèle normalisé à un point précis dans le temps peut être problématique, car toutes les tables changent de façon indépendante, à leur propre rythme.
Dans ce cas, la meilleure solution consiste à créer une vue et à appliquer la sous-clause AS OF
à toute la vue. Cette approche vous permet de dissocier la modélisation de la couche d’accès aux données de l’analyse à un point précis dans le temps car SQL Server applique la clause AS OF
de manière transparence à toutes les tables temporelles impliquées dans la définition de la vue. En outre, vous pouvez combiner des tables temporelles et non temporelles dans la même vue, et AS OF
est appliqué seulement aux tables temporelles. Si la vue ne référence pas au moins une table temporelle, l’application de clauses de requêtes temporelles échoue avec une erreur.
L’exemple de code suivant crée une vue qui joint trois tables temporelles : Department
, CompanyLocation
et LocationDepartments
:
CREATE VIEW [dbo].[vw_GetOrgChart]
AS
SELECT [CompanyLocation].LocID,
[CompanyLocation].LocName,
[CompanyLocation].City,
[Department].DeptID,
[Department].DeptName
FROM [dbo].[CompanyLocation]
LEFT JOIN [dbo].[LocationDepartments]
ON [CompanyLocation].LocID = LocationDepartments.LocID
LEFT JOIN [dbo].[Department]
ON LocationDepartments.DeptID = [Department].DeptID;
GO
Vous pouvez interroger la vue à l’aide de la sous-clause AS OF
et d’un littéral datetime2 :
/* Querying view AS OF */
SELECT * FROM [vw_GetOrgChart]
FOR SYSTEM_TIME AS OF '2021-09-01 T10:00:00.7230011';
Rechercher des modifications sur des lignes spécifiques dans le temps
Les sous-clauses temporelles FROM ... TO
, BETWEEN ... AND
et CONTAINED IN
sont utiles quand vous devez obtenir l’historique de toutes les modifications appliquées à une ligne spécifique dans la table actuelle (ceci s’appelle aussi « audit des données »).
Les deux premières sous-clauses retournent des versions de ligne qui se chevauchent sur une période donnée (c’est-à-dire celles qui ont démarré avant une certaine période et qui se sont terminées après celle-ci), tandis que CONTAINED IN
retourne seulement celles qui existaient dans les limites de la période spécifiée.
Si vous recherchez seulement les versions de ligne non actuelles, vous devez interroger directement la table d’historique pour de meilleures performances pour les requêtes. Utilisez ALL
quand vous devez interroger des données historiques et actuelles sans aucune restriction.
/* Query using BETWEEN...AND sub-clause*/
SELECT [DeptID],
[DeptName],
[ValidFrom],
[ValidTo],
IIF(YEAR(ValidTo) = 9999, 1, 0) AS IsActual
FROM [dbo].[Department]
FOR SYSTEM_TIME BETWEEN '2021-01-01' AND '2021-12-31'
WHERE DeptId = 1
ORDER BY ValidFrom DESC;
/* Query using CONTAINED IN sub-clause */
SELECT [DeptID],
[DeptName],
[ValidFrom],
[ValidTo]
FROM [dbo].[Department]
FOR SYSTEM_TIME CONTAINED IN ('2021-04-01', '2021-09-25')
WHERE DeptId = 1
ORDER BY ValidFrom DESC;
/* Query using ALL sub-clause */
SELECT [DeptID],
[DeptName],
[ValidFrom],
[ValidTo],
IIF(YEAR(ValidTo) = 9999, 1, 0) AS IsActual
FROM [dbo].[Department]
FOR SYSTEM_TIME ALL
ORDER BY [DeptID],
[ValidFrom] DESC;
Contenu connexe
- Tables temporelles
- Clause FROM plus JOIN, APPLY, PIVOT (Transact-SQL)
- Créer une table temporelle versionnée par le système
- Modifier des données dans une table temporelle avec version gérée par le système
- Modifier le schéma d’une table temporelle à version contrôlée par le système
- Arrêt du versioning du système sur une table temporelle avec contrôle de version par le système