Używam podejścia, w którym każdy obiekt, z którym mam do czynienia, zawiera co najmniej jedną instancję o nazwie , w której przechowuję dane, które z czasem ulegają zmianie. Zazwyczaj takie tabele są zgodne z następującą koncepcją:
- mają przyrostek
_HISTORY
w nazwie;
- mają 2 dodatkowe pola,
start_dt
i end_dt
, wskazujące czas życia instancji obiektu;
start_dt
jest NOT NULL
, end_dt
może być NULL
, co oznacza, że instancja jest aktualna i nie jest ograniczona w swoim czasie;
- możliwe jest wstawić zmian przyszłych przestarzałe, że chcesz nową nazwę firmy, aby być aktywowane z
1/Jan-2013
, wtedy trzeba ustawić end_dt
bieżącej instancji 31/Dec-2012 23:59:59
i wstawić nowy rekord z start_dt
z 1/Jan-2013 00:00:00
;
- Czasami dodam również pole
revision
, jeśli konieczne jest śledzenie wersji.
Aby mieć odpowiednie ograniczenia RI z takim projektem, zawsze mam 2 tabele dla wersjonowanych obejcts. Powiedzmy, za Customer
obejct Mam następujący zestaw tabel:
customer (customer_id INTEGER, PRIMARY KEY (customer_id));
customer_history (customer_id INTEGER, start_dt TIMESTAMP, end_dt TIMESTAMP,
name VARCHAR(50), sex CHAR(1), ...,
PRIMARY KEY (customer_id, start_dt));
customer_bank_history (customer_id INTEGER, start_dt TIMESTAMP, end_dt TIMESTAMP,
bank_id INTEGER, iban VARCHAR(34));
we wszystkich innych miejscach używam customer(customer_id)
zbudować kluczy obcych.Odpytywanie rzeczywistych danych klienta jest prosty:
SELECT c.customer_id, ch.name, ch.sex
FROM customer c
JOIN customer_history ch ON c.customer_id = ch.customer_id
AND now() BETWEEN ch.start_dt AND coalesce(end_dt, now());
Dlaczego wolę taką konstrukcję:
- Mam wersjonowany instancji obiektu na poziomie bazy danych w fazie projektowania;
- Muszę przechowywać mniej tabel;
- Nie można uzyskać historii utraconej na wypadek, gdyby ktoś upuścił/zablokował jakiekolwiek wyzwalacze;
- Mogę łatwo planować i utrzymywać przyszłe zmiany.
Mam nadzieję, że to ci pomoże.
Więc główne tabele mają najnowsze dane. Wówczas tabele "historyczne" mają kopie każdej wersji? Czy to nie znosi normalizacji? – StackOverflowNewbie
Tak, pojawia się denormalizacja, jest to cena za prostotę (stany historyczne są generowane automatycznie z prostego 'INSERT',' DELETE', 'UPDATE' na głównej tablicy) i wydajność ostatniej wersji (na przykład główna tabela ma indeksy oparte na danych, podczas gdy historia ma indeksy daty). Jeśli najnowsza wersja nie jest główną wersją do pracy, to podejście może cierpieć z powodu zerwanej normalizacji. – vearutop