Die Datenverwaltung mit Business Time
Erzeugen einer Tabelle mit Business Time
Um eine Tabelle mit Business Time zu erzeugen, sind Spalten für die Start-/Endzeitpunkte des Gültigkeitszeitraums sowie eine PERIOD BUSINESS_TIME-Klausel erforderlich. Die Spalten für die Start-/Endzeitpunkte des Gültigkeitszeitraums können vom Typ DATE oder TIMESTAMP sein.
Im folgenden Beispiel wird eine Tabelle für Kfz-Versicherungspolicen erzeugt, in der auch die Gültigkeitszeiten der jeweiligen Daten hinterlegt sind. Im vorliegenden Beispiel sind die Spalten bus_start und bus_end vom Typ DATE. Mit der Klausel PERIOD BUSINESS_TIME wird Db2 angewiesen, diese Spalten zur Nachverfolgung der Start- und Endzeiten für die Gültigkeit von Geschäftsvorfällen in jedem Satz zu nutzen. Um die temporale Integrität der Daten zu gewährleisten, legt Db2 automatisch eine Bedingung (Constraint) fest, die dafür sorgt, dass die Werte in bus_start vor denen in bus_end liegen.
CREATE TABLE policy ( id INT NOT NULL, vin VARCHAR(10), annual_mileage INT, rental_car CHAR(1), coverage_amt INT, bus_start DATE NOT NULL, bus_end DATE NOT NULL, PERIOD BUSINESS_TIME(bus_start, bus_end), PRIMARY KEY(id, BUSINESS_TIME WITHOUT OVERLAPS) );
Die in der CREATE TABLE-Anweisung definierte Bedingung für den Primärschlüssel nutzt die optionale Angabe BUSINESS_TIME WITHOUT OVERLAPS. Damit wird Db2 angewiesen, nur eindeutige Primärschlüsselwerte für jeden Zeitpunkt in Gültigkeitszeiträumen anzulegen. Im vorliegendem Beispiel sorgt BUSINESS_TIME WITHOUT OVERLAPS also dafür, dass keine zwei Versionen oder Zustände derselben Police gleichzeitig bestehen können.
Mit der Anweisung ALTER TABLE lassen sich vorhandene Tabellen für die Darstellung von Gültigkeitszeiten nutzbar machen. Hierzu müssen die oben erwähnten DATE- oder TIMESTAMP-Spalten eingefügt und PERIOD BUSINESS_TIME definiert werden.
Einfügen von Daten in eine Tabelle mit Business Time
Das Einfügen einer Zeile in eine Tabelle mit Business Time ist einfach: Es müssen lediglich gültige Werte für alle Spalten mit der Bedingung NOT NULL angegeben werden – auch für die Start- und Endzeitpunkte des Gültigkeitszeitraums. Mit folgenden Anweisungen lassen sich einige Zeilen in der Tabelle POLICY mit Business Time einfügen (siehe Abbildung 1). Die Abbildung 2 zeigt das Ergebnis der Operationen.
Die Daten zeigen, dass für Police 1111 im Zeitraum vom 1. Januar 2015 bis zum 1. Januar 2016 eine Deckungssumme von 500.000 € vereinbart war. Ab dem 1. Januar 2016 gilt eine Deckungssumme von 750.000 €. Die Daten zeigen weiterhin, dass vom 1. Mai 2013 bis zum 1. März 2015 für Police 1414 eine Deckungssumme von 750.000 € für ein Fahrzeug mit einer voraussichtlichen Jahreskilometerleistung von 14.000 km vereinbart war. Vom 1. März 2015 bis zum 1. Januar 2016 galten für diese Police eine Deckungssumme von 600.000 € und eine voraussichtliche Jahreskilometerleistung von 12.000 km . Wie wird die für diese Tabelle (mit der Klausel BUSINESS_TIME WITHOUT OVERLAPS) vorgeschriebene zeitliche Eindeutigkeit in der Praxis gewährleistet? Dazu wird folgende INSERT-Anweisung eingegeben:
INSERT INTO policy VALUES(1111,'A1111',10000, 'Y',900000,'2015-06-01','2016-09-01');
Db2 wird diese Anweisung nicht ausführen und stattdessen Fehlermeldung ausgeben, weil versucht wurde, eine Zeile für Police 1111 einzufügen, die für einen Zeitraum gilt, für den bereits eine oder mehrere andere Zeilen für diese Police als gültig definiert sind. Es liegt also eine Verletzung der zeitlichen Eindeutigkeit vor. Soll die Deckungssumme für Police 1111 vom 1. Juni 2015 bis 1. September 2016 angepasst werden, ist dafür eine UPDATE-Anweisung erforderlich.
Aktualisieren von Daten in einer Tabelle mit Business Time
Auch Tabellen, die Gültigkeitszeiträume vorsehen, können mit herkömmlichen UPDATE-Anweisungen aktualisiert werden. Zusätzlich verfügbar ist die Klausel FOR PORTION OF BUSINESS_TIME zur Beschränkung der Aktualisierung auf einen bestimmten Gültigkeitszeitraum. Sind von der Aktualisierung auch Sätze betroffen, die nicht vollständig innerhalb des angegebenen Zeitraums liegt, aktualisiert Db2 die innerhalb der Zeitraumbedingung liegenden Daten und fügt zusätzliche Sätze ein zur Protokollierung der alten Werte für Sätze, die nicht innerhalb des angegebenen Zeitraums liegen.
Beispiel: Die Deckungssumme für Police 1111 soll für den Zeitraum vom 1. Juni 2015 bis 1. September 2016 geändert werden. Die entsprechende UPDATE-Anweisung könnte so aussehen:
UPDATE policy FOR PORTION OF BUSINESS_TIME FROM '2015- 06-01' TO '2016-09-01' SET coverage_amt = 900000 WHERE id = 1111;
Hierbei ist zu beachten, dass die zeitliche Bedingung für die Abfrage (FOR PORTION OF BUSINESS_TIME FROM ... TO ...) hinter dem Tabellennamen steht und nicht Teil der WHERE-Klausel ist.
Wie in Abbildung 2 gezeigt, gab es ursprünglich zwei Zeilen für Police 1111. Beide sind von der UPDATE-Anweisung betroffen, da der zu aktualisierende Gültigkeitszeitraum teilweise innerhalb der in beiden Zeilen gespeicherten Zeiträume liegt. Diese Überlappung ist im oberen Teil von Abbildung 2 dargestellt. Wenn Db2 die Aktualisierung vornimmt, wird jede der ursprünglichen Zeilen in zwei Zeilen geteilt, wie im unteren Teil von Abbildung 2 dargestellt. Db2 passt die Gültigkeitszeiten der Sätze automatisch an.
Abb. 1: Einfügen von Daten in eine Tabelle mit Business Time
Löschen von Daten aus einer Tabelle mit Business Time
DELETE FROM policy FOR PORTION OF BUSINESS_TIME FROM '2015-06-01' TO '2016-01-01' WHERE id = 1414;
Abfragen an eine Tabelle mit Business Time
Für Abfragen nach temporalen Daten muss auch hier analog zu Abfragen mit System Time eine von drei unterstützten Zeitraumangaben in die FROM-Klausel aufgenommen werden. Die Zeitangaben können sowohl in der Vergangenheit als auch in der Zukunft liegen:
- FOR SYSTEM_TIME AS OF ...
- FOR SYSTEM_TIME FROM ... TO ...
- FOR SYSTEM_TIME BETWEEN ... AND ...
SELECT * FROM policy FOR BUSINESS_TIME FROM '2014-01-01' TO '2016-01-01' WHERE id = 1414;
Zusätzliche temporale Funktionalitäten
Bitemporale Tabellen
- Am 15. November 2016 wird die Police 1111 für das Fahrzeug A1111 angelegt. Als Beginn der Laufzeit der Police mit einer Deckungssumme von 500.000 € wurde der 1. Januar 2017 festgelegt.
INSERT INTO policy(id, vin, annual_ mileage, rental_car, coverage_amt, bus_ start, bus_end) VALUES(1111,'A1111',10000, 'Y',500000,'2017-01-01','9999-12-30');
- Am 1. März 2017 wurden die Bedingungen der Police 1111 mit Wirkung ab dem 1. Juni 2017 geändert: Die Deckungssumme wurde reduziert und die Kostenübernahme für Leihwagen entfernt. Das geschah mit folgender UPDATE-Anweisung:
UPDATE policy FOR PORTION OF BUSINESS_TIME FROM '2017-06-01' TO '9999-12-30' SET coverage_amt = 250000, rental_car='N' WHERE id = 1111;
Die Abbildungen 9 und 10 zeigen die Inhalte der Tabellen POLICY und POLICY_HISTORY nach diesen Operationen. (Der Einfachheit halber sind in den Spalten sys_start und sys_end nur die Datums-werte gezeigt und nicht den exakte Zeitpunkt)
- Darüber hinaus wird unter der Police 1111 wegen eines Unfalls am 20. Juni 2017 ein Schadenersatzanspruch geltend gemacht. Der zuständige Sachbearbeiter kann die Rechtmäßigkeit des Anspruchs mit folgender Ab- frage prüfen:
SELECT vin, rental_car, coverage_amt FROM policy FOR BUSINESS_TIME AS OF '2017-06-20' WHERE id = 1111;
- Am 10. Juli 2017 beschwert sich der Kunde und verlangt eine Aufstellung der in den vergangenen zwei Jahren an seiner Police vorgenommenen Änderungen. Diesem Wunsch kann der Sachbearbeiter mit folgender Abfrage nachkommen:
SELECT id, vin, annual_mileage, rental_car, coverage_amt, bus_start, bus_end, sys_ start, sys_end FROM policy FOR SYSTEM_TIME FROM '2015-07-10' TO '2017-07-11' WHERE id = 1111;
Views
- Views können für eine temporale Tabelle mithilfe einer FOR SYSTEM_TIME- oder FOR BUSINESS_TIME-Klausel definiert werden, um die Sicht auf einen bestimmten Zeitpunkt oder Zeitraum zu beschränken. Anschließend können diese Views mit herkömmlichen SQL-Anweisungen abgefragt werden. Abfragen an solche Views dürfen keine FOR SYSTEM_TIME- oder FOR BUSINESS_TIME-Klauseln enthalten, weil die zeitliche Bedingung in der Abfrage mit der zeitlichen Bedingung für die Views im Widerspruch stehen oder zu zweideutigen Ergebnissen führen könnte.
- Die Definition einer View für eine temporale Tabelle ohne eine FOR SYSTEM_TIME- oder FOR BUSINESS_TIME-Bedingung. Solche Views stellen Daten für alle Zeitpunkte dar und lassen sich mit Anweisungen abfragen, die FOR SYSTEM_TIME- oder FOR BUSINESS_ TIME-Klauseln enthalten. Solche Klauseln werden dann automatisch auf alle Tabellen in der View- Definition angewendet, die Perioden für System Time oder Business Time enthalten.
Db2 bietet damit enorme Flexibilität bei der Arbeit mit Views und temporalen Daten. Temporale Bedingungen lassen sich also in der View-Definition oder in Abfragen an Views von temporalen Tabellen nutzen.
Globale Einstellungen über Register-Variable
SET CURRENT TEMPORAL SYSTEM_TIME = '2013-01-01 10:00:00';
SET CURRENT TEMPORAL SYSTEM_TIME = current timestamp – 1 MONTH;
SET CURRENT TEMPORAL BUSINESS_TIME = '2017-06-01';
Fazit
Quellen
- Cynthia M. Saracco, Matthias Nicola, Lenisha Gandhi: „A matter of time: Temporal data management in DB2"
- Db2 auf IBM developerWorksTechnische Artikel, Software, Forum)
https://developer.ibm.com/data/db2/
Kommentare
Bei Updates im Blog, informieren wir per E-Mail.