Für die salopp formulierte Anforderung “in Views mit
mehreren Tabellen schreiben” muß zunächst eine verständliche
Semantik definiert werden: Was soll eigentlich mit den
Basistabellen der View passieren, wenn man “in eine View
schreibt” ?
Beteiligte SQL-Objekte
Das definierte Verfahren wird durch folgende serverseitige
SQL-Objekte implementiert, deren SQL-Code automatisch aus
einer Beschreibung der entsprechenden Virtab erzeugt werden :
-
Eine View (“Virtab-View”) , die das SELECT auf der Virtab durchführt
- Eine in stored procedure (“Virtab-Insert-Prozedure”), die
INSERT auf der Virtab durchführen kann.
Diese und die folgenden Prozeduren werden in der ORACLE-Sprache PL/SQL erzeugt.
- Eine stored procedure (“Virtab-Update-Prozedure”), die
UPDATE auf der Virtab durchführen kann.
- Eine stored procedure (“Virtab-Delete-Prozedure”), die
DELETE auf der Virtab durchführen kann.
- Drei Trigger auf der Virtab-View, die bewirken, das die
SQL-Anweisunen “INSERT INTO virtab_view”, “UPDATE
virtab_view” und “DELETE FROM virtab_view” die
entsprechenden Virtab-Procs aufrufen.
Die eigentliche Implementierung des Virtab-Konzeptes findet
in den drei Virtab-Prozeduren statt. View und Trigger stellen
eigentlich nur ein Zugriffs-Interface dar. Jedes INSERT,
UPDATE oder DELETE wirkt auf genau einen Record der
Virtab-View, dieser Datensatz soll von einem nachfolgenden
SELECT wieder zurückgegeben werden. An die Virtabs-Prozeduren
werden alle Spalten des betroffenen Records der Virtab-View
als Parameter übergeben.
Durch die Anweisung
INSERT INTO v_depts(regional_group, name, street city, state, zip_code)
VALUES ('Dallas', 'research', '3 Walnut Ave', 'Dallas', 'TX','25712') ;
erfolgt also folgender Prozeduraufruf (die Insert-Prozedure
der Virtab “depts” heisst “pi_deps”):
EXEC pi_depts('Dallas', 'research', '3 Walnut Ave', 'Dallas', 'TX', '25712')
Funktion der Prozeduren: Lokalisierung von Records
Eine Virtabdefinition besteht im Kernt, wie jede
View-Definition, aus einem Netz aus Master- und
Detailtabellen, wobei Tabellen gleichzeitig Master und Detail
sein können. Die Tabellen sind durch Fremdschlüssel
miteinander verbunden.
Eine INSERT/UPDATE/DELETE -Operation auf einer Virtab
bedeutet einfach, dass die entsprechende Aktion auf jeder
einzelnen Basistabelle durchgeführt wird, wobei die
Vernetzung der Tabellen untereinander erhalten bleiben soll.
Dazu ist es nötig, dass für jede Basistabelle ein aktueller,
zu bearbeitender Datensatz(record) gesucht wird (bei INSERT
wird zwar kein vorhandener Datensatz bearbeitet, es muss aber
sichergestellt werden, dass der Datensatz noch nicht
existiert).
Ein Basistabellen-Datensatz kann nur mit den
Spalteninformationen gesucht (=”lokalisiert”) werden, die an
die Virtab-Prozedur übergeben wurden, die also als Spalten
der Virtab definiert wurden.
Eine Virtab muss für jede Basistabelle
ausreichende Schlüsselinformation in ihren Spalten enthalten.
|
|
Es muß also für jede Basistabelle eine Spalte in der Virtab existieren, die deren Primärschlüssel
oder einen Zweitschlüssel enthält. Ausnahmen von dieser Regel werden weiter unten und im
Referenzteil dargestellt.
Beispiel: Die Virtab “deps” ist im Definitionsfile wie folgt definiert:
VIRTUALTABLE DEPTS
COLUMN REGIONAL_GROUP// in der ganzen DB gibts nur eine Spalte
// REGIONAL_GROUP: keine weiteren Angaben noetig
COLUMN DEPARTMENT_NAME = DEPARTMENT.NAME // Umbenennung gegenueber DB.
// Spalten auf Mastertable ADDRESS
COLUMN street
COLUMN city
COLUMN state
COLUMN zip_code
;
|
Sie enthält die Basistabellen LOCATION, DEPARTMENT und ADDRESS, wie auch an der
erzeugten View “vt_deps” zu sehen ist:
CREATE VIEW vt_depts AS
SELECT regional_group, department.name department_name,
street, city, state, zip_code
FROM location, department, address
WHERE location.location_id = department.location_id
AND department.address_id = address.address_id;
In der Definition der Demo-Datenbank sind die Primärschlüssel mit PRIMARYKEY und die
benutzbaren Zweitschlüssel mit IDENTIFYING gekennzeichnet.
Das Beispiel ist gleich etwas anspruchsvoller: Die Records der drei Basistabellen werden hier
nämlich über verschiedene Mechanismen lokalisiert. Es werden völlig sichtbarer Zweitschlüssel,
teilweise sichtbarer Zweitschlüssel aus zwei Feldern und ein unsichtbarer Zweitschlüssel
verwendet.
Basistabelle
|
Record lokalisierbar
durch Feld(er)
|
Bemerkung
|
LOCATION
|
regional_group
|
Sichtbarer Zweitschlüssel (IDENTIFYING).
|
DEPARTMENT
|
name, location_id
|
Der Zweitschlüssel wird aus zwei Felder gebildet:
name ist sichtbarer Zweitschlüssel. location_id
ist ein Fremdschlüssel, der auch als Zweitschlüssel
fungiert ( “DEPARTMENT.name” muss nur innerhalb einer
LOCATION eindeutig sein). location_id ist bekannt,
wenn der Master LOCATION lokalisiert wurde.
|
ADDRESS
|
address_id
|
In der Virtab nicht sichtbarer, aber intern
benutzter Fremdschlüssel. Für Spalte “address_id” ist
ein Wert bekannt, sobald ein Record von LOCATION
lokalisiert wurde. Daher brauchen “address_id” nicht
vom Anwender gesetzt zu werden.
|
Ein Record aus ADDRESS ist also lokalisierbar, obwohl keiner seiner Schlüsselfelder Teil der
Virtab ist. Die Abhängigenkeiten der verschVoraussetzung ist, das
Da für die Lokalisierung von Records auch Schlüsselverbindungen zu Mastertabellen
herangezogen werden können (ein Fremdschlüssel darf auch mit IDENTIFYING markiert
werden), müssen die Virtab-Procs das Lokalisieren im allgemeinen von Basistabellen-Records
von Mastertabellen in Richtung Detailtabellen vornehmen. Ist ein Record einer Mastertabelle
lokalisiert wurden, ist zugleich der Primärkey des Masterrecords bekannt. Dieser bildet zugleich
den Wert von Fremdschlüsseln in den Detailtabellen.
Umgekehrt ist der Primärkey eines Masters bekannt, wenn schon ein Detail lokalisiert wurde.
ER2SQL verzichtet aber bei der “Lokalisierungs-Sortierung” nach Möglichkeit auf die Nutzung
dieses Mechanismus.
Das ER-Diagramm
der Datenbank muß sortierbar sein, darf also
keine Master-Detail-Hierarchieschleifen
enthalten.
Für jede Basistabelle muss eine Primärkey-Spalte existieren.
|
|
Diese Forderungen sind aber normalerweise in jeder Datenbank erfüllt.
Das Sortieren des Basistabellen-Netzwerkes und das Lokalisierung von Records stellt den
anspruchsvolleren Teil der Virtabprozeduren dar. Er ist im wesentlichen für alle drei Prozeduren
gleich.
Funktion der Prozeduren: INSERT
In der Insert-Prozedur stellt es keinen Fehler dar, wenn ein Record in einer Basistabelle nicht
lokalisiert werden kann: dann wird er neu in die Basistabelle eingetragen. Der neue Datensatz
benötigt einen neuen Wert für seinen Primärschlüssel. Wenn die Primärschlüsselspalte nicht Teil
der Virtab ist, oder dort NULL übergeben wird, gewinnt die Prozedur den Wert unter
ORACLE aus einer Sequenz mit festem Namen.
Für jeden Primärschlüssel muss eine SEQUENCE mit Namen
“SEQ_<pk_name>” in der Datenbank vorhanden sein.
|
|
Der neu gewonnene Primärschlüsselwert wird über die Prozedurparameter zurückgegeben, und
kann von der Anwendung gleich weiterverarbeitet werden.
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 auf den Basistabellen (jedenfalls auf einer
leeren Datenbank) :
-
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);
Funktion der Prozeduren: UPDATE
UPDATE funktioniert ähnlich: für jede Basistabelle muss ein Record gesucht werden.
Anschliessen kann der Record aktualisiert werden. Da an die Update-Prozedur allerdings nur
der gewünschte neue Datensatz übergeben wird (und nicht auch die vorhandene Version),
können Schlüsselfelder für Basistabellen mit UPDATE nicht geändert werden. (Ausnahmen
siehe Referenzteil).
Wenn ein Record einer Basistabelle nicht lokalisiert werden kann, ist das ein Fehler.
Der SQL-Befehl “UPDATE ... WHERE ... “ auf einer View führt implizit ein SELECT durch.
Die Prozedur wird einmal für jeden Datensatz ausgeführt, der durch die WHERE-Bedingung
ausgewählt wird. Auch wenn mit “UPDATE ... WHERE ...”nur ein Teil der Virtabspalten
gesetzt wird, erhält doch jeder Parameter der Update-Prozedur einen Wert aus dem neuen
View-Record.
Funktion der Prozeduren: DELETE
DELETE ist funktional am einfachsten: Erst wird für jede Basistabelle ein Record lokalisiert,
dann wird dieser Record (über die ermittelten Primärschlüssel) gelöscht. Es wird in umgekehrter
Reihenfolge gelöscht: zuerst Detailtabellen, dann die Mastertabellen.
Die Delete-Prozedur bietet zusätzlich folgenden Service: Sie überprüft beim Löschen einer
Tabelle optional, ob auf diese Tabelle noch von anderen Tabellen aus Referenzen bestehen.
Falls das so ist, wird der Eintrag nicht gelöscht, sondern es gibt eine Fehlermeldung, die den
referenzierenden Tabellenrecord benennt. Dies ist beim Debugging eine wertvolle Hilfe, da
ORACLE bei einer Constraint-Verletzung nur allgemeine Fehlermeldungen produziert.
Funktion der Applikations-Interfaces
Da schon serverseitig die View und die Prozeduren durch Trigger zu einer Einheit verbunden
sind, können Virtabs eigentlich von allen Plattformen aus direkt wie normale Datenbanktabellen
angesteuert werden. Es gibt allerdings Gründe, für verschiedene Entwicklungsumgebungen ein
besonderes Virtab-Interface bereitzustellen.
-
Manche Entwicklungsumgebungen (z.B. Borland Delphi) sind so intelligent, dass sie
RDBMS-Views und RDBMS-Tables voneinander unterscheiden können und das
Schreiben in eine Virtab-View verbieten.
-
Für die Spalten einer Virtab können verschiedene Attribute definiert werden, die den
übergebenen Spaltenwert verändern: Es wurde schon erwähnt, dass bei INSERT ein mit
NULL übergebener Primärschlüssel automatisch mit einem Wert belegt wird. Wurde für
eine Spalte ein Defaultwert angegeben, ist das Verhalten ähnlich.
Diese “intelligente” Wertänderungen müssen mit den Datenmengen-Objekte der
Anwendung synchronisiert werden. Die Anwendung kann zwar nach jedem INSERT ein
SELECT ausführen, das Virtab-Interface synchronisiert aber zuverlässiger und ohne
Neuabfrage.
-
Das Virtab-Interface stellt der Anwendung zusätzliche Informationen über Name und
Eigenschaften der definierten Virtabs bereit, es dient also als auch “Virtab-Dictionary”.
Die Architekur sieht - hier für einen 2-tier - bei Einsatz eines Virtab-Interfaces so aus:
Falls Borland-Delphi als Entwicklungsumgebung für den Client verwendet wird, werden
spezielle Nachfahren von TDataset (TVirtabT) zum Ansteuern der Virtab verwendet. Diese
kapseln View und Prozeduren client-seitig. (Die Darstellung erfolgt hier gegenüber der obigen
gedreht, “A”..”Z” bezeichnen die Tabellen im serverseitigen ER-Diagrammm).
Read more ....
Auf dieser Seite wurde nur das Grundprinzip der Virtab-Prozeduren dargestellt. Dieser Ablauf
kann durch viele Optionen erweitert oder verändert werden (siehe Features und Referenzteil).
|