Bonsoir Vilukariok,
Nous sommes en phase en ce qui concerne le diagramme (MLD).
Envoyé par
Vilukariok
Les 2 tables d'historisation ne sont remplies que lorsqu'une recette change?
Oui. Exemples de scénarios :
1er cas de figure :
Supposons qu’une recette (table RECETTE) ait la valeur suivante (pour mon confort personnel, je passe en CHAR(04) ) :
RecetteId = 'r01'
IngredientId= 'i01'
Ordre = 'o01'
RecetteDepuis = '2000-01-15'
QuantiteDepuis = '2000-01-15'
Quantite = 100
Et que la quantité passe à 200 à la date du '2000-04-22' :
On historise donc et la table QUANTITE_HISTORIQUE va héberger la ligne suivant :
RecetteId = 'r01'
IngredientId= 'i01'
Ordre = 'o01'
QuantiteDurantDeb = '2000-01-15'
QuantiteDurantFin = '2000-01-21' _____________ coquille de ma part, lire : '2000-04-21'
Quantite = 100
Tandis qu’en échange, dans la table RECETTE on aura la ligne suivante :
RecetteId = 'r01'
IngredientId= 'i01'
Ordre = 'o01'
RecetteDepuis = '2000-04-15' ________________ coquille de ma part, lire : '2000-01-15'
QuantiteDepuis = '2000-04-22'
Quantite = 200
La recette < 'r01', 'i01', 'o01'> existe toujours, simplement on trace la modification des quantités.
Deuxième cas de figure :
C’est l’attribut Ordre qui change de valeur. Considérons la recette :
RecetteId = 'r01'
IngredientId= 'i01'
Ordre = 'o01'
RecetteDepuis = '2000-01-15'
QuantiteDepuis = '2000-01-15'
Quantite = 100
Et supposons qu’elle soit remplacée le '2000-07-14', par la nouvelle recette 'r01', 'i01', 'o02'>. La recette d’ordre 'o01' peut être conservée telle quelle dans la table RECETTE si on la considère comme étant finalement toujours active, ou bien on peut préférer l’expulser dans la table RECETTE_HISTORIQUE (je rappelle que la table RECETTE exprime ce qui est actif et n’a pas intérêt à être surchargée par des données mortes qui la rendraient obèse). La table RECETTE_HISTORIQUE accueille alors la ligne suivante :
RecetteId = 'r01'
IngredientId= 'i01'
Ordre = 'o01'
RecetteDurantDeb = '2000-01-15'
RecetteDurantFin = '2000-07-13'
La trace de la quantité sera évacuée dans la table QUANTITE_HISTORIQUE :
RecetteId = 'r01'
IngredientId= 'i01'
Ordre = 'o01'
QuantiteDurantDeb = '2000-01-15'
QuantiteDurantFin = '2000-07-13'
Quantite = 100
Tandis que la nouvelle recette viendra remplacer l’ancienne dans la table RECETTE :
RecetteId = 'r01'
IngredientId= 'i01'
Ordre = 'o02'
RecetteDepuis = '2000-07-14'
QuantiteDepuis = '2000-07-14'
Quantite = 500 (ou l’ancienne valeur 100, c’est vous qui voyez).
En tout cas, une chose est sûre : tout ce qui part en historisation a forcément une date de fin. Quand je lis ceci :
Envoyé par
Vilukariok
je ne sais pas si il y a une utilité à pré remplir les tables d'historisation en laissant vide les champs "Fin".
Je tremble en vous lisant (horresco referens comme dit l'autre)...
Laisser « vides » les dates de fin est contraire au principe même de l’historisation où l’on ne doit raisonner qu’en intervalles (ou périodes si vous préférez). Si vous scrutez attentivement les structures de tables que je vous ai proposées, vous constaterez que chaque attribut est qualifié NOT NULL, sans exception.
Pour en revenir au plat de résistance :
Avec le trigger que je vous avais proposé, vous aviez pu constater que le recouvrement (ou chevauchement) d’intervalles était interdit. Pour aller plus avant, voici les règles de base de l’historisation quant aux contraintes auxquelles celle-ci doit se plier (elles font partie des nine requirements définis par Date, Darwen et Lorentzos) :
1) Si la base de données montre qu’il y a une recette r au jour j, elle ne doit contenir qu’un seul tuple qui exprime ce fait.
Ainsi, si la table RECETTE dit que la recette existe au jour j, la table RECETTE_HISTORIQUE doit être muette à ce sujet, tandis que si la table RECETTE_ HISTORIQUE dit que la recette existe au jour j, c’est la table RECETTE qui doit être muette.
N.B. En relationnel, un tuple est ce que l’on appelle une ligne de table en SQL.
2) Si la base de données montre qu’il y a une recette r à j et j+1, elle ne doit contenir qu’un seul tuple qui exprime ce fait. Je vous laisse démontrer le bien-fondé de cette contrainte.
3) Si la base de données montre qu’il y a une recette r au jour j (table RECETTE ou table RECETTE_HISTORIQUE), elle doit aussi montrer qu’il existe un tuple qui exprime une quantité au jour j pour cette recette (table RECETTE ou table QUANTITE_HISTORIQUE).
4) Si la base de données montre qu’il existe un tuple qui exprime une quantité au jour j pour la recette r (table RECETTE ou table QUANTITE_HISTORIQUE), elle ne doit contenir qu’un seul tuple qui exprime ce fait.
5) Si la base de données montre qu’il existe un tuple qui exprime une quantité à j et j+1 pour la recette r (table RECETTE ou table QUANTITE_HISTORIQUE), elle ne doit contenir qu’un seul tuple qui exprime ce fait.
6) Si la base de données montre qu’il existe un tuple qui exprime une quantité au jour j pour la recette r (table RECETTE ou table QUANTITE_HISTORIQUE), elle doit aussi montrer qu’il existe un tuple au jour j pour cette recette (table RECETTE ou table RECETTE_HISTORIQUE).
Il existe d’autres contraintes, mais celles que j’ai énumérées sont incontournables.
Par ailleurs, vous pourriez préférer que la table RECETTE_HISTORIQUE soit absorbée par la table QUANTITE_HISTORIQUE, pour cause de double emploi apparent. Mais attention, les intervalles [RecetteDurantDeb:RecetteDurantDeb] et [QuantiteDurantDeb:QuantiteDurantDeb] vivent a priori chacun sa vie. Par ailleurs, que faire le jour où, en plus de l’attribut Quantite, vous définiriez un attribut supplémentaire pour les recettes (la qualité recherchée, l’inventeur de la chose ou que sais-je) ? Vous seriez coincé et obligé de bien réfléchir à toutes les conséquences sur les applications déjà développées d'un retour à l'architecture que je vous ai proposée. La table RECETTE_HISTORIQUE est une sorte de tour de contrôle pour l'historisation.
En tout cas, les six contraintes qui précèdent font l’objet de triggers intéressants (je vous laisse réfléchir un peu au pseudo-code correspondant), il y a un prix à payer pour que la base de données ne finisse pas par ressembler à n’importe quoi (quand on voit ce qu'on voit...)
A suivre...
Partager