Virtabs: Funktion der Virtab-Prozeduren

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:

  1. 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.
  2. 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.

 

[Konzepte] [Virtab-Prozeduren] [LINK, FOREIGNKEY] [QUERY: Mehrfachzugriffe] [USES und Verschmelzen] [Schreibschutz, -zwang] [Daten-Teilmengen] [Synthetische Spalten] [User-SQL]