Ciao
La storicizzazione dei dati è un problema frequente in aziende di una certa dimensione. Nel mio caso mi sono trovato a gestire un business che chiedeva uno storico dei dati online.
Mi spiego meglio: alcune entità che persistiamo su DB sono già di per se storiche, un esempio sono i movimenti di un cc, o di cassa, ma il problema viene per fare un esempio se noi vogliamo creare un vincolo di integrità tra un movimento ed un tasso di cambio, la cosa si complica, perchè il tasso di cambio varia molte volte al giorno anche mantenendo la stessa divisa (la moneta).
Uno degli esempi classici di storicizzazione in questo caso userebbe una chiave doppia per la tabella dei camb di tipo ID e TS (timestamp dell'operazione), così facendo esisterebbero per quell'ID di cambio (es: ID 1 da euro a dollaro) vari tassi di cambio così come negoziati continuamente in borsa. Quindi nella tabella dei movimenti dovremmo avere in chiave esterna la chiave composta da ID e TS.
Tutto ok, ma cosa succederebbe se volessi mettere in chiave in un altra tabella l'ultima versione e sempre l'ultima del cambio? Ad esempio se voglio mettere in chiave il mio cc in valuta estera con la mia valuta di riferimento.... in quel caso la chiave dovrebbe si corrispondere ad un ID di cambio (euro dollaro) ma non specificando quale da un punto di vista temporale perchè intendo utilizzare sempre l'ultimo. Alcuni mettono in chiave solo l'ID tralasciando il TS, ma così perdono l'integrità referenziale tra le tabelle.... andando a vanificare molte delle potenzialità di un DB relazionale come Oracle, SQL Server o DB2.
La soluzione migliore a mio parere è splittare la tabella su due livelli, in pratica realizzando una tabella CambiParent e una CambiChild, nella parent avremo solo l'ID, e nella child o un secondo ID che rappresenta l'occorrenza temporale dell'entità Cambi generica con un TS non in chiave, o solo il TS in chiave a tutti gli effetti splittando le due chiavi iniziali (ID e TS) in due tabelle. Tutti gli altri attributi dell'entità Cambi resterebbero in CambiChild. Così facendo quando saro un vincolo di integrità con il dato temporale si utilizzerà il TS (o l'ID della tabella Child), altrimenti nel caso di una connessione alla entità generica, basterà mettere una FK (chiave esterna) collegata all'ID della tabella Parent così da garantire il vincolo di integrità, all'uso in join poi, basterà fare una top sul TS per ricavare l'ultima.