web-dev-qa-db-fra.com

Changez le comportement des tables temporelles pour enregistrer les changements de valeur réelle plutôt que les mises à jour factice

Actuellement, les articles que j'ai lus sur des tableaux temporels appuient la responsabilité du nettoyage du code de l'application. Est-il possible de configurer les tables temporelles pour enregistrer des modifications de valeur de colonne particulières au lieu de lorsque l'instruction de mise à jour est appelée sur la table?

Exemple pour le comportement attendu:

USE Master;
GO

-- Create test database
CREATE DATABASE [TemporalTables];
GO

USE TemporalTables;
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

-- Hidden period columns
CREATE TABLE [dbo].[PersonHistory](
    [PersonID] [int] NOT NULL,
    [EmailAddress] [varchar](75) NULL,
    [IsSubscribed] [bit] NULL,
    [SysStartTime] datetime2  NOT NULL,  
    [SysEndTime] datetime2 NOT NULL
);    

CREATE CLUSTERED COLUMNSTORE INDEX IX_PersonHistory   
   ON PersonHistory;   
CREATE NONCLUSTERED INDEX IX_PersonHistory_ID_PERIOD_COLUMNS   
   ON PersonHistory (SysEndTime, SysStartTime, PersonID);   
GO   

CREATE TABLE [dbo].[Person](
    [PersonID] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
    [EmailAddress] [varchar](75) NULL,
    [IsSubscribed] [bit] NULL,
    [SysStartTime] datetime2 GENERATED ALWAYS AS ROW START HIDDEN NOT NULL,  
    [SysEndTime] datetime2 GENERATED ALWAYS AS ROW END HIDDEN NOT NULL,
    PERIOD FOR SYSTEM_TIME (SysStartTime,SysEndTime)     
)    
WITH
(   
      SYSTEM_VERSIONING = ON (HISTORY_TABLE = dbo.PersonHistory)   
);  

-- Current Time UTC
SELECT sysutcdatetime();
-- Value: 2017-03-14 16:11:56.6294004

--Insert Rows
INSERT [dbo].[Person] ([EmailAddress], [IsSubscribed]) VALUES ('[email protected]', 1);
GO

INSERT [dbo].[Person] VALUES ('[email protected]', 1);
GO

INSERT [dbo].[Person] ([EmailAddress], [IsSubscribed], [SysStartTime], [SysEndTime])
VALUES ('[email protected]', 1, default, default);
GO

-- Query the main table
SELECT *, SysStartTime, SysEndTime
FROM dbo.Person
-- Shows all changes for specific PK (for inserts to show up)
SELECT *, SysStartTime, SysEndTime
FROM dbo.Person
FOR SYSTEM_TIME ALL
where Personid IN (1,2,3);

-- Current Time UTC
SELECT sysutcdatetime();
-- Value: 2017-03-14 16:13:27.0374068

--Update Rows (Actual Updates)
UPDATE [dbo].[Person] SET [EmailAddress] = '[email protected]' WHERE [EmailAddress] = '[email protected]';
GO
UPDATE [dbo].[Person] SET [EmailAddress] = '[email protected]' WHERE [EmailAddress] = '[email protected]';
GO
--Update Rows (Dummy Update)
UPDATE [dbo].[Person] SET [EmailAddress] = '[email protected]' WHERE [EmailAddress] = '[email protected]';
GO

-- Query the history table
SELECT *
FROM dbo.PersonHistory

-- !!!
-- What I'd want is that the Id = 3 update to not get saved since the data did not change.
-- Also a way I can limit the number of columns I want this behavior on.
-- PersonID    EmailAddress                                                                IsSubscribed SysStartTime                SysEndTime
-- ----------- --------------------------------------------------------------------------- ------------ --------------------------- ---------------------------
-- 1           [email protected]                                                         1            2017-03-14 16:12:29.5018193 2017-03-14 16:13:27.0374068
-- 2           [email protected]                                                         1            2017-03-14 16:12:29.5118172 2017-03-14 16:13:27.1484051
-- !!!

Question similaire mettant en évidence ce comportement:

Les tables temporelles changent de journal lorsqu'il n'y en a pas?

Je cherche une solution de contournement pour le comportement mentionné.

Modifier la capture de données serait capable de gérer cela (ou même des déclencheurs personnalisés pour cette affaire), mais j'explique si je pouvais bénéficier des tables temporelles avec l'enregistrement d'historique sélectif.

Le défi est que nous avons un travail de l'ETL qui touche souvent les colonnes syncdatatime souvent, et nous voulons exclure ou inclure certaines colonnes, n'enregistrez ainsi que lorsque la valeur de données réelle change, de préférence avec les tables temporelles.

4
D.S.

Sur une plongée supplémentaire, il semble que cela relève actuellement: gérer la conservation des données historiques dans des tables temporelles vers la version système comme une solution réactionnaire au problème, au lieu d'une configuration antérieure.

Et ils proposent trois approches:

  1. Base de données
  2. Cloison de table
  3. Script de nettoyage personnalisé

Il y a quelques autres beaux articles que j'ai trouvés, qui répondent partiellement à ma question, cependant, j'aimerais que je puisse gérer ce comportement au point de création de données plutôt que le nettoyage, je demanderais donc plus d'informations au cas où quelqu'un l'ait , ou si cela change dans le futur.

Autres articles:
[.____] Gestion de l'historique de la table temporelle dans SQL Server 2016
[.____] Considérations et limitations de la table temporelle

2
D.S.