In diesem Kapitel wird der Algorithmus der Virtab-Prozeduren näher erklärt.
Verhalten bei Insert
Einfügeoperationen werden kaskadierend durchgeführt, d.h.
fehlende Einträge in Master-Tabellen werden automatisch
erzeugt und mit Feldwerten der Virtab initialisiert.
Beispiel:
INSERT INTO vt_depts (regional_group, department, address, city, state, zip_code)
VALUES ('Dallas','research','3 Walnut ave','Dallas','TX','25712') ;
bewirkt die Ausführung folgender drei Anweisungen:
INSERT INTO location (location_id,regional_group)
VALUES (seq_location_id.NEXTVAL,'Dallas');
INSERT INTO address (address_id,street,city,state,zip_code)
VALUES (seq_address_id.NEXTVAL,'3 Walnut ave','Dallas','TX','25712') ;
INSERT INTO department (department_id, name,location_id,address_id)
VALUES
(seq_department_id.NEXTVAL,'research',gemerkte_location_id,
gemerkte_address_id);
Wäre der Master-Eintrag in location schon vorhanden gewesen,
würde dort nur der Primärschlüssel gelesen und für das
“INSERT INTO department” in den internen Variablen
gespeichert. Wäre allerdings ein MUSTCHANGE auf location
gesetzt, würde das Vorhandensein des Master-Records als
Fehler gewertet.
“Localisation by detail”:
Obwohl ADDRESS technisch gesehen der Master von DEPARTMENT
ist, wird sie nicht vor DEPARTMENT lokalisiert, weil ADDRESS
keine Identifying-Felder hat, und auch der Primärschlüssel
nicht Teil der Virtab ist.
Das bedeutet, dass man umgangssprachlich nur insofern über eine Adresse reden kann, als man beschreibt: "Dies ist die Adresse von ...". Eine Adresse wird also hier nur über ein bekanntes DEPARTMENT identifizierbar; nach ADDRESS wird über den fremdschlüsselwert DEPARTMENT.address_id gesucht. In Folge davon kann ein und dieselbe Adresse (Kombination der einzelnen, nicht identifizierenden Felder) mehrfach in der Tabelle vorkommen. Erst dadurch wird es möglich, das Umziehen eines Departments als simples Update der Adresse abzubilden, das die Existenz der neuen Adresse in der Tabelle nicht voraussetzt
Der Einfügealgorithmus im Detail:
- Ordne die an der Virtab beteiligten Tabellen nach ihren
Abhängigkeitsverhältnissen. Zuerst kommen Tabellen, deren
aktueller Record durch die in der Virtab-Prozedur
übergebenen IDENTIFYING- bzw. PRIMARYKEY-Feldwerte
eindeutig bestimmt ist. Danach kommen Tabellen, die durch
Virtab-Feldwerte und die Primärschlüssel (oder
Fremdschlüssel) bereits lokalisierter Tabellenrecords
eindeutig bestimmt sind, etc.
Es gibt dabei
prinzipiell zwei verschiedene Arten, Schlüsselverknüpfungen
zur Lokalisierung von Records in Tabellen zu verwenden:
a) Prinzipiell versucht ER2SQL immer zunächst einen Record
in der Mastertabelle zu lokalisieren. Der dadurch gefundene
Primärschlüssel des Masterrecords (= Fremdschlüssel der
Detailtabelle) wird aber nur dann als Kriterium bei der
Suche nach dem Detailrecord verwendet, wenn der
Fremdschlüssel in der Detailtable IDENTIFYING ist.
("erst Master suchen, dann Detail”) b) Wenn der
Record einer Mastertabelle weder durch Werte von
übergebenen Virtab-Feldern noch durch Fremdschlüssel
spezifiziert ist, wird zuerst ein Record aus einer
Detailtabelle der Mastertabelle lokalisiert. Der
Fremdschlüssel in der Detailtabelle dient dann als
Suchkriterium in der Mastertabelle ("erst Detail
suchen, dann Master”), wobei nicht notwendigerweise ein
Masterrecord eindeutig identifiziert werden kann. Dieses
Vorgehen ist Standard bei einer n:m-Beziehung zwischen zwei
Tabellen, die über eine Verknüpfungstabelle ohne
Identifying-Felder in Form zweier 1:n-Verbindungen
realisiert ist.
- Gehe der Reihe nach durch die geordneten Tabellen und
stelle in jeder Tabelle die Existenz eines passenden
Datensatzes sicher, indem die Tabelle nach dem
Primärschlüssel oder dem Zweitschlüssel (was immer an
Feldwerten in der INSERT-Prozedur übergeben wurde)
durchsucht wird.
2.1)
wurde genau ein Eintrag gefunden: OK (falls nicht MUSTCHANGE), merke den Primärschlüssel.
2.2) wurde kein Eintrag gefunden: erzeuge neuen Record,
nimm neuen Wert für Primärschlüssel aus der Sequenz der
jeweiligen Tabelle 2.3) wurden mehrere Einträge
gefunden: Fehler! Offenbar wurde der Primärschlüssel nicht
angegeben, und nicht alle Zweitschlüsselfelder sind NOT
NULL.
Es stellt keinen Fehler dar, wenn die INSERT-Prozedur in
allen Tabellen schon vorhandene Datensätze vorfindet, solange
die Tabellen nicht MUSTCHANGE sind. Garantiert wird
lediglich, dass nach dem Durchlauf jeder Datensatz vorhanden
ist.
Ist beim Insert ein Datensatz in einer Tabelle schon
vorhanden, werden die Daten nicht entsprechend der
Virtab-Feldwerte aktualisiert! Nur beim Neuanlegen eines
Datensatzes wird der Datensatz mit Werten aus Virtab-Spalten
initialisiert. Als Folge davon kann nach einem Insert
eine View-Abfrage für Felder, die nicht IDENTIFYING sind,
andere Werte liefern. Echte Schreib-/Lesekonsistenz ist
gewährleiststet, wenn direkt nach jeder INSERT-Prozedur die
UPDATE-Prozedur mit identischen Parametern aufgerufen wird.
Dieses Verhalten soll schon vorhandene Daten durch
Modifikationen bei INSERT schützen.
Verhalten bei Update
UPDATE-Operationen verlaufen generell ähnlich wie INSERT-Operationen:
Zuerst werden in jeder betroffenen Tabelle die aktuellen
Records lokalisiert. Dann werden die Datenfelder jedes
aktuellen Records mit den in der UPDATE-Prozedur übergebenen
Werten per UPDATE aktualisiert. Sollen Zweitschlüsselspalten
(IDENTIFYING-Spalten) geändert werden, muss die Virtab den
Primärschlüssel der Tabelle enthalten. Das Aktualisieren
unterbleibt, wenn die entsprechende Tabelle NOCHANGE ist.
Verhalten bei Delete
Auch Löschoperationen sind kaskadierend, d.h. nach dem
Löschen eines Records in einer Detail-Tabelle wird der
Eintrag in einer Mastertabelle ebenfalls gelöscht, wenn er
von keiner anderen Detailtabelle mehr referenziert wird (dies
ist eine andere Funktionalität als das bekannte DELETE
CASCADE).
Beim Überprüfen der Referenzen auf einen Record werden
potentiell alle Tabellen der Datenbank, nicht nur die
Tabellen der jeweiligen Virtab, berücksichtigt. Dadurch kann
die Löschoperation sehr aufwendig werden.
DELETE-Operationen verlaufen ähnlich wie INSERT- und
UPDATE-Operationen. Zuerst werden in jeder betroffenen
Tabelle die aktuellen Records lokalisiert. Dann wird
versucht, den aktuellen Record in jeder Tabelle der Virtab zu
löschen. Das Löschen beginnt dabei in den Detailtabellen. Das
Löschen unterbleibt, wenn die entsprechende Tabelle NOCHANGE
ist, oder wenn es noch Referenzen auf den zu löschenden
Record gibt. Kann noch nicht einmal der Eintrag in der/den
Detailtabelle(n) gelöscht werden, gibt es eine Fehlermeldung.
Nicht löschbare Records in Tabellen, die MUSTCHANGE sind,
führen ebenfalls zu Fehlermeldungen.
Als Konsequenz des beschriebenen Löschmechanismus ist
hervorzuheben, dass keinesfalls der gesamte der
DELETE-Prozedur übergebene Record (alle einzelnen Feldinhalte
der Spalten) tatsächlich gelöscht wird, wenn eine
Fehlermeldung unterbleibt: Das erfolgreiche Löschen des
letzten Detaileintrags sowie der Attribute aus evtl.
MUSTCHANGE-Tabellen stellt bereits den Gesamterfolg der
Löschoperation dar, da nun der ursprüngliche Record nicht
mehr von der Virtab dargestellt werden kann. Gleichwohl wird
intern versucht, "soviel wie möglich" zu löschen.
Dieses Verhalten korrespondiert sinngemäß mit dem Verhalten
beim Einfügen, wo nur "so wenig wie nötig" wirklich
neu eingefügt wird, um den Virtab-Datensatz als Ganzes zu
erfüllen. Insert- und Delete-Prozeduren einer Virtab bilden
damit funktional exakt konträre Werkzeuge: Mit der
Delete-Prozedur einer Virtab kann man das wieder löschen, was
mit der Insert-Prozedur der gleichen Virtab, ausgehend von
gleichen Datenbestand, eingefügt wurde.
Besonderheiten
Bei der Ermittlung der Verknüpfungsstruktur in den INSERT-,
UPDATE- oder DELETE-Prozeduren gelten folgende Besonderheiten
bzgl. NULL-Werten und Primärschlüsseln:
- NULL-Spalten im Zweitschlüssel werden einfach ignoriert.
Als Suchkriterien nach Records werden nur ausgefüllte
Zweitschlüsselfelder verwendet. Das Defaultverhalten von
Oracle würde sonst nie Datensätze liefern.
- Ist der Primärschlüssel einer Tabelle in einer Virtab
enthalten und im aktuellen Datensatz mit einem Wert belegt,
werden alle Zweitschlüssel dieser Tabelle bei der Suche
ignoriert und es wird nur mit Hilfe des Primärschlüssels
gesucht. Bei einem UPDATE bewirkt dies, dass zusätzlich
angegebene Zweitschlüsselfelder wie Datenfelder behandelt
werden: so können Zweitschlüsselwerte geändert werden.
- Kommt in einer Virtab ein Primärschlüssel einer Tabelle
vor, und ist der Wert für diesen Schlüssel bei der
INSERT-Prozedur NULL, so wird immer ein neuer Datensatz
erzeugt! Die Suche nach schon vorhandenen Einträgen in der
Datenbank unterbleibt in diesem Fall.
|