web-dev-qa-db-fra.com

Table temporelle qui n'utilise pas le temps système

Nous souhaitons mettre en œuvre des tables temporelles dans SQL Server 2016. Nous créons une datawarehouse et développons des tables de dimensions de type 2 de type 2.

Pour le début, nous voulons que cela dépend de la date de transaction et non du temps getdat actuel. Nous reproduisons une histoire de transactions. Exemple ci-dessous, le client dispose d'une salle de sport ou d'un statut bancaire et passe d'inactif, actif ou en attente de la date de transaction.

Nous avons actuellement cela.

CREATE TABLE dbo.Department
(
    CustomerId int primary key,
    MembershipStatus int,
    TransactionDate datetime
 );

Nous aimerions créer une table comme celle-ci.

CREATE TABLE dbo.DepartmentHistory
(
    CustomerId int primary key,
    MembershipStatus int,
    TransactionDate datetime,
    BeginDatetime datetime,
    EndDatettime datetime
 );

Exemple d'utilisation serait:

  1. première transaction client le 3/5/2018 comme en attente de p
 + ------------- + -------- + ----------- + --------- + [.____] | CustomerId | Statut | BEGINDE | Enddate | 
 + ------------ + -------- + ----------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------- - + [.____] | 1 | P | 3/5/2018 | Null | 
 + ------------ + -------- + ----------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + -------- - + 
  1. deuxième transaction est le 21/04/2018 est actif A
[.____] + ------------- + -------- + ----------- + --------------- - + [.____] | CustomerId | Statut | BEGINDE | Enddate | 
 + ------------ + -------- + ----------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------- --- + 
 | 1 | P | 3/5/2018 | 14/12/2018 | [.____] | 1 | Un | 4/21/2018 | Null | 
 + ------------ + -------- + ----------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + ------------- + -------- --- + 
2
user162241

Tables temporelles sont Système - Versed1, donc le seul moyen de " Définir manuellement" L'horodatage d'une ligne d'historique donnée consiste à modifier le temps d'exploitation au moment où la ligne est modifiée qui ... vous ne voulez probablement pas faire.

Si vous voulez " Définir manuellement" Time limites sur une table d'historique de sorte qu'elle prend en charge Syntaxe de requête temporelle , vous pouvez le faire en appliquant manuellement une table temporelle sur le dessus de vos données existantes. Ceci est un peu délicat et nécessite que les données sous-jacentes se conforment aux règles de la version de l'historique temporel. Google est parsemé de divers articles de blog sur ce dos lorsque des tables temporelles ont été introduites; Puisque je n'ai pas joué avec ce cas d'utilisation exacte depuis un moment, je vais désormais créer des liens arbitrairement à cet exemple qui semble prometteur .

Démo Quickie

N'oubliez pas qu'une table temporelle vers la version système est en fait deux tables - A "MAINTENANT" Table and a "Historique" Table spéré ensemble. ..

create table dbo.b_now ( 
     i int not null primary key 
    ,info varchar(10)
    ,start_dt datetime2 generated always as row start
    ,end_dt   datetime2 generated always as row end
    ,period for system_time (start_dt, end_dt)
) with (system_versioning = on (history_table = dbo.b_history));
go

insert b_now (i,info)
values 
 (1,'AAA')
,(2,'BBB');
go
update b_now set info = 'XXX' where i = 1
go
select * from b_history
select * from b_now
go

Notez que pendant que b_now semble être la "table de base" et prend en charge la syntaxe temporelle - il n'est qu'un objet distinct. Supprimer la liaison de la version système entre les objets renforce ceci.

Utilisation de ces informations pour "Version manuelle"

Garder cela à l'esprit - et rappelez-vous que nous pouvons changer SYSTEM_VERSIONING à partir de ON à _ OFF et retour ON.à à nouveau, nous pouvons dire que SQL Server d'appliquer arbitrairement (et ignorer arbitrairement) les règles de versement du système à une paire d'objets arbitraires si longtemps. comme...

  1. les schémas correspondent
  2. les données sont conformes exactement comme elle serait si elle avait Été System Versed

Mais je veux exemple de code!

Oui, je pensais que tu pouvais - alors essayez ceci ...

drop table if exists a_now ,a_history;
go
create table a_now ( 
     i    int not null primary key
    ,info varchar(10)
    ,start_dt datetime2 not null
    ,end_dt   datetime2 not null 
        -- you'll want this CHECK later...
        check (end_dt = convert(datetime2,'9999-12-31 23:59:59.9999999'))
);
go
create table a_history (
     i        int not null
    ,info     varchar(10)
    ,start_dt datetime2 not null
    ,end_dt   datetime2 not null
);
go

declare @end_of_time datetime2 = '9999-12-31 23:59:59.9999999';

insert a_now values 
 (1,'XXX','2017-01-01',@end_of_time)
,(2,'BBB','2017-01-01',@end_of_time)

insert a_history values
 (1,'AAA','2016-01-01','2017-01-01');
go
select * from a_now
select * from a_history

... a l'air beaucoup comme b_now et b_history, n'est-ce pas? Dommage que ce n'est pas une table système appropriée ...

alter table a_now
    add period for system_time (start_dt, end_dt);
go
alter table a_now
    set (system_versioning = on (history_table = dbo.a_history));
go

Attendre wut ...? Vous pouvez même plonger une vue sur la table "MAINTENANT" pour cacher votre abus des conventions de dénomination.

create or alter view a 
as
select * from a_now
go

select * 
from a 
for system_time as of '2016-06-01'

Ok oui ... mais comment puis-je ajouter de nouvelles lignes M. Smarty Pants?

Très soigneusement ... c'est comme ça.

alter table a_now
    set (system_versioning = off);
alter table a_now
    drop period for system_time;
go

declare @end_of_time datetime2 = '9999-12-31 23:59:59.9999999';

insert a_now values 
 (3,'CCC','2018-01-01',@end_of_time);

update a_now set 
     start_dt = '2018-01-01'
    ,info = 'YYYY'
where i = 1;

insert a_history 
values 
  (1,'XXX','2017-01-01','2018-01-01')

alter table a_now
    add period for system_time (start_dt, end_dt);
go
alter table a_now
    set (system_versioning = on (history_table = dbo.a_history));
go

select * from a for system_time as of '2017-06-01'

Je laisse le lecteur (vous) pour terminer le INSERT/UPDATE/DELETE logique et pertinent DROP/re -SET Vérification du système dans un module récupéable.


1. N.B. Ceci est allongé avec la syntaxe le period for SYSTEM_time Dans le DDL requis pour la création d'une table temporelle

3
Peter Vandivier