Multimedia- Datenbanksysteme

Werbung
Vorlesung
MultimediaDatenbanksysteme
Wintersemester 1999/2000
Wolfgang Kowarschick
Fachhochschule Augsburg
Draft (2. März 2000)
2
Inhalt
1 Einführung
7
1.1
Modelle, Fakten, Datenmodelle und Daten . . . . . . . . . . . . .
7
1.2
Historie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
1.3
Datenbankmodelle . . . . . . . . . . . . . . . . . . . . . . . . .
9
1.3.1
Extreme Ansätze für Datenbanksysteme . . . . . . . . . . 10
1.3.2
4GL-Datenbanksysteme . . . . . . . . . . . . . . . . . . 11
1.3.3
Besondere Aspekte von Datenbanken . . . . . . . . . . . 12
2 Entity-Relationship-Modelle
15
2.1
Entities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.2
Relationships . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.2.1
2.3
Multiplizitäten . . . . . . . . . . . . . . . . . . . . . . . 17
Schlüssel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3 Das Relationenmodell
25
3.1
Grundkonzepte . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.2
Überführung eines ER-Modells in ein relationales Schema . . . . 28
3.3
3.2.1
„Schema F“ . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.2.2
Optimiertes „Schema F“ . . . . . . . . . . . . . . . . . . 30
Die Relationale Algebra und SQL . . . . . . . . . . . . . . . . . 33
3.3.1
Die Identität . . . . . . . . . . . . . . . . . . . . . . . . 35
3.3.2
Die Projektion . . . . . . . . . . . . . . . . . . . . . . . 36
3.3.3
Die Selektion . . . . . . . . . . . . . . . . . . . . . . . . 37
3.3.4
Vereinigung, Durchschnitt, Differenz . . . . . . . . . . . 38
3
Draft (2. März 2000)
3.4
3.5
3.3.5
Kartesisches Produkt und Join . . . . . . . . . . . . . . . 39
3.3.6
Division . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
3.3.7
Subanfragen (Subqueries) . . . . . . . . . . . . . . . . . 50
Aggregation und Gruppierung . . . . . . . . . . . . . . . . . . . 55
3.4.1
Aggregation ohne Gruppierung . . . . . . . . . . . . . . 55
3.4.2
Aggregation mit Gruppierung . . . . . . . . . . . . . . . 56
Sortierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.5.1
3.6
3.7
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . 58
Modifikation des Datenbestandes . . . . . . . . . . . . . . . . . . 58
3.6.1
Insert . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
3.6.2
Delete . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
3.6.3
Update . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
3.6.4
Allgemeine Anmerkungen . . . . . . . . . . . . . . . . . 60
Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
3.7.1
Das View-Update-Problem . . . . . . . . . . . . . . . . . 64
4 Oracle
67
4.1
SQLPlus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
4.2
Date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
5 Datenbankensysteme und Multimedia
71
5.1
Anforderungen an ein Multimedia-Datenbanksystem . . . . . . . 71
5.2
Relationale Datenbanksysteme und Multimedia . . . . . . . . . . 72
5.2.1
BLOBs . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
5.2.2
CD-ROM-Datenbanken . . . . . . . . . . . . . . . . . . 74
5.2.3
RAID (Plattenfarmen) . . . . . . . . . . . . . . . . . . . 75
5.3
Volltextindexe (Inhaltssuche) . . . . . . . . . . . . . . . . . . . . 77
5.4
Hypermedia (navigierende Suche) . . . . . . . . . . . . . . . . . 86
5.4.1
5.5
Das Dexter-Referenz-Modell . . . . . . . . . . . . . . . . 90
Koppelung WWW
5.5.1
MMDBS . . . . . . . . . . . . . . . . . . 92
JDBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Draft (2. März 2000)
4
6 Objektorientierte Datenbanken
6.1
99
ODMG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
6.1.1
Primitive Datentypen . . . . . . . . . . . . . . . . . . . . 101
6.1.2
Komplexe Datentypen . . . . . . . . . . . . . . . . . . . 101
6.1.3
ODL . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
6.1.4
OQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
7 Normalformtheorie
7.1
7.2
7.3
Funktionale Abhängigkeit . . . . . . . . . . . . . . . . . . . . . 111
7.1.1
Reduzierte funktionale Abhängigkeiten . . . . . . . . . . 112
7.1.2
Schlüsselkandidaten . . . . . . . . . . . . . . . . . . . . 112
Normalformen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
7.2.1
Erste Normalform (1NF) . . . . . . . . . . . . . . . . . . 112
7.2.2
Zweite Normalform (2NF) . . . . . . . . . . . . . . . . . 112
7.2.3
Dritte Normalform (3NF) . . . . . . . . . . . . . . . . . 113
7.2.4
Boyce-Codd-Normalform (BCNF) . . . . . . . . . . . . . 114
Zerlegung (Dekomposition) eines Relationenschemas . . . . . . . 114
7.3.1
7.4
111
weitere Normalformen . . . . . . . . . . . . . . . . . . . 117
Normalformen und ER-Modellierung . . . . . . . . . . . . . . . 118
A Literatur
121
A.1 Datenbanken . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
A.2 Objektorientierung . . . . . . . . . . . . . . . . . . . . . . . . . 121
5
Draft (2. März 2000)
Draft (2. März 2000)
6
Kapitel 1
Einführung
✎
1.1 Modelle, Fakten, Datenmodelle und Daten
Der Mensch kann die Welt/Realität nicht direkt erfassen. Er bildet letztlich immer
(zumindest auf geistiger Ebene) Modelle der Realität. Neue Erkenntnisse kann
er nur gewinnen, wenn er neue Fakten in seine Modellwelt einordnen oder die
Modellwelt geeignet abändern kann.
Realitätsausschnitte Modelle
Fakten
Musik
Notensystem
Eine kleine Nachtmusik
Thermodynamik
Differentialgleichungen , Chemie
Formeln
Meereswellen
Chaostheorie
Simulationen
Städte, Länder etc.
Landkarten
Augsburger Stadtplan
Mathematik und Informatik bilden ebenfalls abstrakte Modelle für die „Realität“,
allerdings wesentlich formaler als dies mit natürlichen Sprachen möglich ist.
Fakten werden in der Informatik normalerweise in Form von sogenannten Daten,
d. h. als Zeichenketten modelliert. Multimedia-Daten (Audio, Video, Bilder etc.)
werden von Datenbanksystemen meist lediglich als sogenannte BLOBs (Binary
Large OBjects), d. h. als lange Folge von Bits dargestellt, deren Bedeutung einem
DB-System unbekannt sind.
Für gegebene Realitätsausschnitte können, um die Bedeutung von Fakten festzulegen, sogenannte Datenmodelle entwickelt werden (siehe beispielsweise die
bereits bekannte „objektorientierte Modellierung“).
Die Abbildung eines Realitätsausschnittes auf Fakten eines Modells oder
– spezieller – auf Daten eines Datenmodells stellt immer einen sogenannten Abstraktionsschritt dar. Abstraktion ermöglicht einerseits ein besseres
Verständnis, bedeutet andererseits aber einen Präzisionsverlust, d. h., (hoffentlich)
7
Draft (2. März 2000)
unwesentliche Teile der Realität werden vernachlässigt.1
Datenmodelle sind normalerweise nicht sehr umfangreich, die zugehörigen
Datenbestände können dagegen häufig beliebig groß werden. Die Aufgabe von
Datenbankmanagementsystemen (DBMS) ist es, große, langlebige Datenbestände effizient zu verwalten. Unter einem Datenbanksystem (DBS) verstehe ich ein
Datenbankmanagementsystem (die eigentliche DB-Software) zusammen mit den
zugehörigen Datenmodellen, Datenbeständen und weitere Komponenten (wie grafische Benutzerschnittstelle, Report Generator, WWW-Schnittstelle etc.). Mit Datenbanksystemen werden wir uns in dieser Vorlesung befassen.
Beispiele
– Banken (Die Datenbankpioniere)
– Deutsche Bahn AG
– Bibliotheken (Library of Congress (LoC), viele multimediale Daten)
– Metreologische Institute
– NASA/ESA (Satelliten, Marssonde etc.)
– Versandhandel (Kataloge)
– etc.
Datenbestände der DB AG
– Fahrpläne
– Tarife
– Streckennetz
– Wagenpark
– Stromnetz
– Personal
– etc.
Frage:
Wie sieht beispielsweise ein Datenmodell für Fahrpläne aus?
kurze Antwort: Fahrpläne werden normalerweise als Tabellen realisiert. Das Datenmodell legt die Strukturen dieser Tabellen sowie die erlaubten
Inhalte der einzelnen Zeilen und Spalten fest.
1
Der Präzisionsverlust ist manchmal allerdings erheblich. Man denke nur an die zahllosen Interpretationsmöglichkeiten eines einzelnen Musikstückes wie der kleinen Nachtmusik.
Draft (2. März 2000)
8
Datenbestände Bibliotheken
– Texte, Bilder, Tonträger, Videos
(z. B. LoC: Originalwalzen für Edison-Phonographen, Orginalfilme von
Laurel/Hardy etc.)
– Kataloge
– Benutzerverwaltung
– Bestellwesen
– etc.
Geo-Informationssysteme
Ein Spezialgebiet der DB-Welt stellen die sogenannten Geo-Informationssysteme
(GIS) dar. In derartigen Systemen geht es darum, 2- und 3-dimensionale Landkarten zu verwalten. Die Kostenrelation eines typischen GIS-Systems sieht ungefähr
wie folgt aus:
Kosten Hardware:
Faktor 1
Kosten Software:
Faktor 10
Kosten Datenerfassung: Faktor 100
1.2 Historie
Die historische Entwicklung von Datenbanksystemen:
1. Hierarchische DBS (IMS von IBM)
2. Netzwerk-DBS (CODASYL; UDS von Siemens)
3. Relationale DBS (System R von IBM)
4. Objektorientierte DBSe (überspitzt formuliert: Rückschritt zu 2.)
Vor- und Nachteile von RDBS (Schemamodifikation ohne Effizienzeinmußen
möglich) und OODBS (sehr effizient für Spezialanfragen – genauso wie Netzwerk-DBS – wenig effizient für „nicht-schema-konforme“ Anfragen).
1.3 Datenbankmodelle
Datenmodelle für Datenbanken sollen folgende Eigenschaften haben:
1. verständlich, insbesondere nicht zu umfangreich
9
Draft (2. März 2000)
2. ausreichend präzise und ausreichend vollständig für bestimmte Zwecke
3. effizient realisierbar, d. h., eine gewünschte Auskunft kann bzgl. eines zugehörigen Datenbestandes „schnell“ erteilt werden
4. leicht modifizierbar, um schnell an neue Gegebenheiten angepasst werden zu
können ohne dass vorhandene Datenbestände wertlos werden
Lösungen:
ad 1. einheitliche Formalisierungsmethode mit wenigen formalen Elementen
ad 2. möglichst mächtige Formalisierungsmethode
ad 3. kleiner, aber mächtiger Satz von effizient zu realisierenden Elementaroperationen
1970 kam Codd auf die Idee, mathematische Relationen (d. h. Tabellen) und
relationale Operationen (Vereinigung, Durchschnitt, Differenz, kartesisches Produkt (Join)) zur Verwaltung von Massendaten einzusetzen.
Es hat sich im Lauf von bald 30 Jahren gezeigt, dass dieser Formalismus, so einfach er auch ist, sehr wohl geeignet ist, hochkomplexe Datenmodelle zu erstellen
und die zugehörigen Daten effizient zu verwalten.
Das Relationenkalkül hat allerdings auch einige Schwächen. Und so verwundert
es nicht, dass im Laufe der letzten 30 Jahre auch andere Formalismen entwickelt
wurden, allen voran die objektorientierten Systeme. Verdrängen werden sie die relationalen Systeme allerdings nicht so schnell – es zeichnet sich vielmehr ab, dass
in Zukunft Mischungen aus beiden Welten, die sogenannten objektrelationalen
Systeme eine immer größere Bedeutung erlangen werden.
✎
✎
✎
!"#$%
&'
(*)$
&)$+)-,*/.102)*
3
4$57698:6<;=
?>
1.3.1 Extreme Ansätze für Datenbanksysteme
Natürlichsprachliche Datenbanksysteme
Die an leichtesten zu handhabenden Datenbanksysteme wären diejenigen, die direkt natürlichsprachliche Beschreibungen (= Datenmodelle) und Fakten verarbeiten könnten (siehe Bordcomputer von Raumschiff Enterprise).
Darstellung: Text
@
Draft (2. März 2000)
Bilder, Töne
ABABA
10
Auskünfte:
Information Retrieval
(z. B. OMNIS, WAIS, LEXIS)
Änderungen: Text-/Bild-/Audio-/ ABACA Editoren
Vorteile:
einfach handzuhaben, mächtig
Nachteile:
derzeit leider nur ansatzweise realisierbar, da volles Sprachverständnis implementiert werden müsste
3GL-Datenbanksysteme
Wenn natürlichsprachliche Ansätze nicht funktionieren, warum dann nicht einfach
vorhandene algorithmische Sprachen (C++, Java, Pascal ABABA ), d. h. Sprachen der
dritten Generation (3GL2 ) einsetzen?
Darstellung: direkte Nachbildung von z. B. Papierformularen durch Listen, Bäume, Geflechte etc.
Auskünfte:
Spezialprogramme
Änderungen: Spezialprogramme
Vorteile:
gewohnte Repräsentation und Verarbeitung
Beispiel: (mechanisches Pferd)
Nachteile:
aufwendig, starr, Mehrbenutzerbetrieb schwierig
Beispiele:
frühe Flug- und Banksysteme
1.3.2 4GL-Datenbanksysteme
Für heutige Datenbanken wurden Sprachen und Formalismen oberhalb von 3GLSprachen aber natürlich unterhalb natürlichsprachlicher Systeme entwickelt.
relationale Systeme
Darstellung: Relationen (Tabellen) + Integritätsbedingungen (Invarianten), um
fehlerhafte Datenbankinhalte zu vermeiden
Auskünfte:
deklarative (nicht-algorithmische), d. h. beschreibende Sprache: relationale Algebra (SQL: select ACABA from ABABA where)
Änderungen: Satz von Modifikationsoperationen (SQL: insert, delete, update) unter Beachtung von Integritätsbedingungen
Vorteile:
2
einfach handzuhaben, effizient (mittels Hilfsdatenstrukturen wie BBäume (R. Bayer), R-Bäume etc.), weit verbreitet
1GL = Hardware-Codierung, 2GL = Assemblersprachen
11
Draft (2. März 2000)
Nachteile:
nicht turingmächtig, d. h., es gibt Probleme, die zwar mit algorithmischen Sprachen, nicht jedoch mit gängigen relationalen Systemen gelöst werden können. Leider sind diese Probleme nicht nur
theoretischer, sondern durchaus praktischer Natur. Beispiel: Wegsuche in großen Netzwerken wie Bahnnetz, Stromnetz, Internet etc.
Workaround: Einbettung von relationalen (4GL)-Sprachen in algorithmische (3GL)-Sprachen D impedance missmatch
objektorientierte Systeme
Darstellung: Klassen und Objekte
Auskünfte:
Methoden
Änderungen: Methoden
Vorteile:
Nachteile:
✎
✎
verständlich und benutzerfreundlich, turingmächtig
kein mathematischer Formalismus (nur Ansätze) D Effizienz leidet
wegen fehlender Optimierungstechniken;
sehr jung und daher unausgereift im Vergleich zu relationalen Systemen;
Integritätsbedingungen werden nur sehr rudimentär unterstützt
"! #$%
&E>
?F
1.3.3 Besondere Aspekte von Datenbanken
Im Vergleich zu typischen 3GL-Anwendungen weisen Datenbanken einige Besonderheiten auf:
Lebensdauer
Die Daten leben wesentlich länger als einzelne Programmausführungen. In 3GLSprachen kann dies allerdings mittels Dateien realisiert werden, in denen die Daten zwischen zwei Programmausführungen abgelegt werden.
Öffentlichkeit und Qualität
Die Daten werden von (vielen) verschiedenen Programmen verschiedener Programmautoren bearbeitet D Qualität und Richtigkeit der Daten sind fraglich.
Fehler verseuchen daher langsam eine Datenbank und leben lange
rotten“.
Draft (2. März 2000)
12
D
DBs „ver-
Beispiel aus der Praxis: Bibliotheksbestandsdaten mit Erfassungsjahren 98, 97,
97 ABABA sowie 1998, 1997, 1996 ACABA abhängig vom Erfasser D Sortierung nach
Erfassungsdatum schlägt fehl.
Abhilfe: geeignete Schutzmaßnahmen
– Integritätsüberwachung
– Zurücksetzen auf fehlerfreien Zustand im Fehlerfall (Abort, Recovery)
– Benutzerverwaltung und Zugriffsschutz
– Teamwork, Groupwork, CSCW (computer supported cooperative work)
Dies alles wird von 3GL-Sprachen nicht unterstützt.
Simultanbearbeitung
Dieselben Daten werden gleichzeitig (parallel auf Mehr- oder pseudoparallel auf
Einprozessorrechnern) von mehreren Programmen bearbeitet.
D
Synchronisation des Ablaufs durch das Datenbanksystem.
Dies wird von 3GL-Sprachen auch nicht unterstützt.
In diesem Zusammenhang ist der Begriff der Serialisierbarkeit von Bedeutung:
Eine Ablaufsteuerung heißt serialisierbar (seriell, konsistent), wenn es für jede Menge GIHCJBABABABJ&GK von parallellaufenden Transaktionen (= elementare Arbeitsschritte eines Datenbanksystems) mindestens eine serielle (lineare) Anordnung
dieser Transaktionen gibt, sodass die Nacheinanderausführung der einzelnen
Transaktionen in dieser Reihenfolge dasselbe Ergebnis liefert wie die parallele
Ausführung.
LMM
z. B.
RBS
GIH S
G
N GPO TVU G XW GPQ W GIH W GYO
GPQ
Gegenbeispiel
Prozess A: lese a; a:=a+1, schreibe a;
Prozess B: lese a; a:=a*2, schreibe a;
a:=5; A; B; D
a=12
a:=5; B; A; D
a=11
a:=5; B||A; (A und B laufen parallel)
D a=12 oder a=11 oder a=6 oder a=10
13
Draft (2. März 2000)
ein möglicher paralleler Ablauf
Prozess A
lese a (=5)
Prozess B
lese a (=5)
a := a+1 (=6)
a := a*2 (=10)
schreibe a (=10)
(über)schreibe a (=6)
Eine serielle Ablaufsteuerung verhindert derartige Fehler (a=6 oder a=10).
Draft (2. März 2000)
14
Kapitel 2
Entity-Relationship-Modelle
Ursprung: [Chen, 1976]
2.1 Entities
Das Entity-Relationship-Modell (ER-Modell) kann als Vorläufer der modernen
objektorientierten Modelle, wie z. B. OMT oder UML, angesehen werden.
Objekte werden im ER-Modell Entities genannt. Entities haben Attribute, den Methodenbegriff gibt es allerdings (zumindest im ursprünglichen ER-Modell) von
Chen [1976] nicht. Eine Menge von Entities mit denselben Attributen (aber i. Allg.
unterschiedlichen Attributwerten) heißt Entity-Menge (entity set). Entity-Mengen
entsprechen den Klassenextensionen in objektorientierten Systemen. Einen Entitynamen zusammen mit den zugehörigen Attributnamen und -typen bezeichnet
man als Entitytyp. Entitytypen entsprechen Klassendefinitionen in objektorientierten Systemen.
Heute werden meist sogenannte EER-Modelle (Extended ER) eingesetzt. Diese
haben viele Aspekte der objektorientierten Modellierung übernommen. Im weiteren subsummiere ich unter dem Begriff ER alle gängigen ER-Varianten d. h. auch
EER-Modelle.
Ein wesentlicher Unterschied zu objektorientierten Modellierungstechniken ist
jedoch, dass Entities normalerweise keine OIDs im objektorientierten Sinne
zugeordnet sind. Anstelle dessen werden sogenannte Schlüsselattribute gekennzeichnet, deren Werte eine Entity eindeutig identifizieren. Ein typisches Schlüsselattribut ist Personalnummer. In ER-Modellen ist der Designer also selbst
verantwortlich für die Vergabe von Identifikatoren.
Ein anderer Unterschied zu objektorientierten Modellen ist, dass in ER-Modellen meist direkt mit Attributen gearbeitet wird. Methoden werden normalerweise
nicht unterstützt.
15
Draft (2. März 2000)
2.2 Relationships
Zwischen Entitymengen können Beziehungen (Relationships) bestehen. In OMT
heißen Beziehungen Assoziationen. Beziehungen können ebenso wie Entitytypen
eigene Attribute besitzen.
Beispiele
Entitymenge
Beziehung
Person
besitzt
Entitymenge
Auto
Name
Kennzeichen
Erstzulassung:Datum
Mann
is a
Person
Auto
has a
Motor
Motor
is part of
Auto
UML-Notation
Person
Auto
Name
Kennzeichen
besitzt
Erstzusassung:
Datum
Mann
Person
Auto
Motor
Draft (2. März 2000)
16
2.2.1 Multiplizitäten
Genauso wie in UML kann man die Multiplizität (Vielfachheit) einer Beziehung
genauer festlegen. Man beachte, dass die im Folgenden vorgestellte graphische
Notation nur beispielhaft ist. Jedes ER-Modellierungswerkzeug verwendet seine
eigene Symbolik.
1:1-Beziehungen
Jeder Angestellte hat genau eine Personalakte. Umgekehrt gehört jede Personalakte zu genau einem Angestellten.
Angestellter 1
hat
Angestellter 1
1
Personalakte
1
Personalakte
UML
1:n-Beziehungen und n:1-Beziehungen
Jeder Angestellte arbeitet für genau eine Firma, jede Firma hat beliebig viele Angestellte
Angestellter
n
arbeitet für
Angestellter 0..*
1
Firma
1
Firma
UML
m:n-Beziehungen
Jede Person kann von beliebig vielen Firmen Aktien besitzen, und jede Firma
kann beliebig viele Aktionäre haben.
Person
m
Person
0..*
arbeitet für
17
n
Firma
0..*
Firma
UML
Draft (2. März 2000)
Weitere Beziehungen
Wie wir bereits von UML kennen, kann man Multiplizitäten noch wesentlich genauer beschreiben:
Optionalität: Jede Frau hat höchstens einen (Ehe-)Mann und umgekehrt.
Mengenbeschränkungen: Ein PKW hat 3 (Schumi!) bis 10 Räder
Et cetera
Diese Beziehungen können auch in ER-Diagrammen ausgedrückt werden:
Frau
0-1
PKW
1
Ehegatte
0-1
Mann
hat
3-10
Räder
Bei der Überführung eines ER-Modells oder eines UML-Modells in ein relationales Datenbankschema ist allerdings die (grobe) Unterscheidung von 1:1-, 1:n
und m:n-Beziehungen zunächst meist ausreichend. Eine genauere Spezifikation
der Multiplizitäten wird erst in einem zweiten Schritt benötigt, und zwar bei der
Formulierung von Integritätsbedingungen, die das Datenbanksystem automatisch
überwachen soll.
✎
✎
"! #$%
&EF
[Z
Anmerkung
Die hier vorgestellte Art der Notation von Multiplizitäten hat (sowohl in ER-Diagrammen als auch in UML-Diagrammen) einen gravierenden Nachteil: Sie ist nur
für Zweierbeziehungen, nicht jedoch für Dreier-, Vierer-, Fünfer- ABABA Beziehungen
geeignet. Der Grund dafür ist, das die Multiplizitäten immer bei gegenüberliegenden Entitymengen notiert werden.
n
Firma
Angestellte
Dieses Diagramm liest man wie folgt:
Die Firma beschäftigt beliebig viele Angestellte.
Das funktioniert bei Mehrfachbeziehungen nicht mehr. Wie sehen hier die Multiplizitäten aus?
Draft (2. März 2000)
18
1:1
1:n
n:1
n:m
A
B
a1
a2
a3
a4
a5
b1
b2
b3
b4
b5
a1
a2
a3
a4
a5
b1
b2
b3
b4
b5
a1
a2
a3
a4
a5
b1
b2
b3
b4
b5
a1
a2
a3
a4
a5
b1
b2
b3
b4
b5
Abbildung 2.1: Veranschaulichung der Standardbeziehungen
19
Draft (2. März 2000)
hört
Vorlesung
Student
Hochschule
Professor
Es gibt daher Modellierungstechniken (wie z. B. die Informationsanalyse von
Prof. Kern-Bausch), die die Multiplizitäten genau anders herum platzieren.
Firma
1-n
beschäftigt
0-1
Person
Dieses Diagramm liest man wie folgt:
Eine Firma beschäftigt 1 bis n Personen, d. h. beliebig viele Personen, und
jede Person ist bei einer oder keiner, d. h. bei höchstens einer Firma beschäftigt.
Das obige Diagramm kann nun wie folgt notiert werden:
Student
0-n
hört
Vorlesung
1-n
Hochschule
0-5
Professor
Ein Student hört beliebig viele Vorlesungen, eine Hochschule bietet viele Vorlesungen an, ein Professor hält bis zu 5 Vorlesungen.
Bei Modellierungstechniken wie UML, die mit Mehrfachbeziehungen nicht gut
umgehen können, sollte man jede Mehrfachbeziehung durch eine neue EntityMenge (Klasse) und mehrere Zweifachbeziehungen zu ersetzen.
Draft (2. März 2000)
20
Student
n
hört
n
Vorlesung
n
1
bietet an
Hochschule
0-5
liest
1
Professor
Dieses Diagramm enthält mehr Information als das vorherige. Dennoch könnte
es noch weitere Einschränkungen geben, die nicht direkt im Diagramm dargestellt werden können, wie z. B. „Studenten dürfen Vorlesungen nicht an mehreren Hochschulen belegen“. Derartige Bedingungen werden normalerweise einfach
textuell in das Diagramm eingefügt und später als Integritätsbedingung formuliert.
Anmerkung 2
Entitymengen bzw. Klassen werden meist durch Substantive beschrieben, Beziehungen dagegen durch Verben (Person besitzt Auto). Leider ist diese Faustregel
nicht allgemeingültig, wie man schon am Beispiel „hört Vorlesung“ gesehen hat.
Weitere Beispiele: Prüfungen vs. prüft, Vorgang vs. bearbeitet
Wir werden im Folgenden noch sehen, dass in relationalen Datenbanken der Unterschied zwischen Entities und Relationships völlig verschwindet: Beides wird
durch Tabellen dargestellt.
Anmerkung 3
In dieser Vorlesung wird im Weiteren nur noch die bereits bekannte UML-Notation verwendet, auch wenn von Entities und Relationships die Rede ist. Es wird
vorausgesetzt, dass die Grundprinzipien der objektorientierten Modellierung bekannt sind (Vorlesung MMProg) und dass der Unterschied ER UML (ER: keine
Methoden, keine OIDs) klar ist.
2.3 Schlüssel
Eine Entitymenge ist im wesentlichen eine Menge von Tupeln:
{(Name: "Wolfgang", Geb: 1961, Tel: 325),
(Name: "Anna", Geb: 1961, Tel: 377),
(Name: "Hans", Geb: 1964, Tel: 235)
}
21
Draft (2. März 2000)
Da es sich um eine Menge handelt, kann es jedes Tupel höchstens einmal geben.
In unserem Betrieb gibt es also keine zwei Wolfgangs, die 1961 geboren und die
Telefonnummern 325 haben.
In einer Entitymenge bilden alle Attribute zusammen immer einen Identifikator
für das Tupel, den sogenannten trivialen Schlüssel.
Allerdings kann es in einem Betrieb mit vielen 1000 Mitarbeitern schon mal passieren, dass zwei Mitarbeiter den gleichen Namen und das gleiche Geburtsdatum
haben. Wenn dann auch noch beide im gleichen Zimmer mit nur einem Telefon
sitzen, kann man diesen Sachverhalt in der Datenbank nicht mehr darstellen.
Dieses Problem lösen die Unternehmen mit einer Personalnummer, d. h. mit einem
weiteren Attribut, welches für jeden Mitarbeiter eindeutig ist. Die Personalnummer entspricht einem OID in OO Systemen.
{(PN: 007, Name: "Wolfgang", Geb: 1961, Tel: 325),
(PN: 008, Name: "Wolfgang", Geb: 1961, Tel: 325),
ABACA
}
In diesem Fall bildet bereits das Attribut PN alleine schon einen Schlüssel. Für jede Tabelle wird normalerweise ein sogenannter Primärschlüssel definiert. In ERDiagrammen werden die Primär-Schlüsselattribute meist durch Unterstreichung
markiert. Attribute, deren Wert nicht unbedingt ausgegeben werden muss (die also
den Wert NULL annehmen können), werden mit einem Stern * markiert. Schlüsselattribute können nie den NULL-Wert annehmen, werden also nie mit * markiert.
Person
PN
Name
Geb
Tel*
Im Zusammenhang mit Schlüsseln gibt es viele Fragen:
1. Welche Attributkombinationen kommen als Schlüssel in Frage?
2. Welche der Schlüssel sind minimal (d. h., man kann kein Attribut weglassen, ohne die Schlüsseleigenschaft zu zerstören)? Minimale Schlüssel heißen
Schlüsselkandidaten (candidate keys).
3. Welcher der Schlüsselkandidaten soll als Primärschlüssel verwendet werden?
Jedes Datenbanksystem kann den Zugriff auf Primärschlüssel-Attribute besonders effizient gestalten, da es für diese Attribute immer einen sogenannten
Primärindex anlegt.
Draft (2. März 2000)
22
4. Ist ein Schlüsselkandidat wirklich für jeden nur denkbaren Datenbankzustand
ein Schlüssel? (Oft denkt ein DB-Designer nicht daran, dass es auch in einem
5-Mann-Betrieb zwei „Sepp Maier“ geben kann und so die Attribute Nachname und Vorname gar keinen Schlüsselkandidaten bilden.)
5. Ist ein Schlüssel eindeutig bzgl. einer Entitymenge oder bzgl. der ganzen Datenbank? (OIDs sind bzgl. einer oder gar mehrerer Datenbanken eindeutig.)
6. Sind Schlüssel wiederverwendbar (Personalnummern, Matrikelnummern,
Autonummern)?
Anmerkung
Man kann auch den lesenden Zugriff auf andere Schlüsselkandidaten und Nichtschlüsselattribute effizienter gestalten, indem man für derartige Attribute sogenannte Sekundärindexe definiert. Allerdings hat die Einführung von vielen Sekundärschlüsseln einen deutlichen Effizienzverlust der Modifikationsoperationen
(Einfügen, Ändern, Löschen) zur Folge.
\^]_<_)-,$`#*a4I]_3
]b_`c"4d
]_3#[efhgij3kml$oni#Epqbrq#$l$3n
#*istb`rqvuwyxz4dbz4|{
Beispiel
Entity-Menge Prüfung:
Professor, Student, Fach, Datum, Uhrzeit, Raum, Note
Schlüsselkandidaten:
Student, Fach, Datum
Student, Professor, Datum, Uhrzeit
Entity-Menge Adresse: Straße, Hausnummer, PLZ, Ort
Schlüsselkandidat: Straße, Hausnummer, PLZ
Der Ort ist bekannt, wenn die PLZ bekannt ist (PLZ }
Ort).
Man spricht hier von einer sogenannten funktionalen Abhängigkeit.1
Schlüsselkandidaten für Adressen in den USA:
City Street ZIP
In manchen Staaten gilt:2 City Street
Außerdem gelte: ZIP }
CITY.
1
2
}
ZIP.
Anmerkung von Michael Schulze: Diese funktionale Abhängigkeit gilt in Deutschland nicht. Es
gibt mehrere Orte mit gemeinsamer PLZ.
Anmerkung von Claus Tews: Diese Abhängigkeit gilt i. Allg. auch nicht. Es gibt verschiedene
Orte (z. B. Berlin) mit gleichen Straßennamen (z. B. Unter den Linden). Ob es amerikanische
Staaten gibt, in denen diese Abhängigkeiten wirklich gelten, ist unbekannt.
23
Draft (2. März 2000)
✎
Unter disen Voraussetzungen gibt es zwei Schlüsselkandidaten:
City Street
ZIP Street
✎
✎
✎
"! #$%
&`Z
bE~
pC4I#$"4db.€<]_b
4dy,*3
‚*3
Draft (2. März 2000)
24
Kapitel 3
Das Relationenmodell
3.1 Grundkonzepte
Das Relationenmodell (RM) von Codd kann (im Gegensatz zu den meisten OOModellen) mathematisch exakt definiert werden. Hier sollen allerdings nur die
wesentlichen Grundideen vorgestellt werden.
1. Domänen
Eine Domäne ist eine Menge von Werten. Typische Domänen sind Integer,
String
(Varchar), Bool, Float
„
„ etc., Integer* (= Integer ƒ
Null … ), String* (= String ƒ Null … ) etc.
In SQL enthält jeder Elementary defaultmäßig den Nullwert Null. Braucht
man diesen nicht, so muss man dies explizit angeben: Integer NOT NULL
etc.
2. Relationen
6
6
Eine Teilmenge †7‡‰ˆŠH
ABABA ˆK eines kartesischen Produktes1 von Domänen heißt Relation. Relationen kann man sich als Tabellen vorstellen in
deren ‹ -ter Spalte nur Elemente der Domäne ˆŒ enthalten sind:
Beispiel
6
Person ‡ String Integer
Wolfgang 37
Marianne 36
Sibylle 11
.
.
.
3. Tupel
Ein Element einer Relation heißt Tupel. Tupel stellen also die Zeilen der Tabellen dar.
1
Zur Erinnerung: Das kartesische Produkt von mehreren Mengen ist die Menge aller Tupel, die sich aus diesen Mengen bilden lassen:
Ž|P‘Š’“C”d–•—‘a’“™˜šP›B‘œ
¥ CžŽŸ™¥”d–˜Ÿ ¡IzŽŸI”IP›¢ ¡IzŽŸP•1–˜Ÿ ¡zŽŸ–•—£›¢ –™I”I£˜Ÿ ¡&I”I£›1 ¡I¤P•B£˜Ÿ ¡¤P•1–›1 ¡‘
’ œ`B”d™” ¡I”IP•¢ –&¦¦P¦j™•BI”& ¡I¤•—–•1 ¡¦P¦P¦j™§BI”& ¡I¤§—–•1 ¡¦P¦¦y&¦¦&¦¡‘¢¦
25
Draft (2. März 2000)
4. Attribut
Die „Spalten“ einer Relation heißen Attribute. Sie erhalten eindeutige (und
sinnvolle) Namen.
5. Relationenschema
Ein Relationenschema besteht aus einem Relationnamen gefolgt von einer
Liste von Attributen mit zugeordneten Domänen:
†©¨£ªwH «¬ˆŠHXJCABABA¢JIª­K®«€ˆKt¯
6. (Relationales) Datenbankschema
Eine Menge von Relationenschemata heißt Datenbankschema
7. (Relationale) Datenbank
Ein Datenbankschema (Datenmodell) zusammen mit einer Menge von zugehörigen Relationen (Fakten) heißt (relationale) Datenbank (RDB).
Anmerkungen
1. Objektorientierte Datenbanken werden ebenso wie RDBen über Datenmodelle und Fakten definiert:
Datenmodelle: Klassendefinitionen (+ Methodenimplementierungen)
Fakten:
Klassenextensionen
2. Relationen sind Mengen im mathematischen Sinn:
D a) es gibt keine Duplikattupel
b) die Reihenfolge der Tupel ist irrelevant
Achtung: Implementierungen von RDBS realisieren Mengen meist als Listen
(mit Duplikaten und Reihenfolge) oder als Multimengen (mit Duplikaten ohne Reihenfolge).
3. In der obigen Definition von Relationenschema ist die Reihenfolge der Spalten wesentlich. Eigentlich ist dies jedoch unwichtig, da die Spalten eindeutig
benannt werden. Daher werden wir in Zukunft unser Augenmerk mehr auf die
Namen der Spalten als auf deren Reihenfolge richten.
4. Die Struktur einer Datenbank, d. h., das Datenbankschema wird durch sogenannte DDL-Anweisungen (Data Definition Language, create table,
alter table, drop table etc.) festgelegt.
5. Der Inhalt einer Relation (die Fakten) wird durch sogenannte
DML-Anweisungen (Data Manipulation Language, select, insert,
modify, delete) abgefragt und modifiziert. Das Datenbankschema selbst
wird meist auch in (leider nicht genormten) Tabellen abgelegt und kann
daher mit DML-Befehlen (select) gelesen werden. Die Manipulation der
Systemtabellen erfolgt dagegen immer mit DDL-Befehlen.
Draft (2. März 2000)
26
6. Für RDBS gibt es meist eine wesentliche Einschränkung. Als Attributdomänen dürfen keine komplexe Datentypen wie Liste, Menge, Feld oder
Tupel (Record) verwendet werden, sondern nur primitive Datentypen wie
Integer, Float, Bool und String2
Anstelle der Tabelle:
Name
Hobbies
Wolfgang {Akkordeon,Fahrrad,Flöte}
Sonja
{Flöte,Ballett}
muss man die Tabelle
Name
Wolfgang
Wolfgang
Wolfgang
Sonja
Sonja
Hobby
Akkordeon
Fahrrad
Flöte
Flöte
Ballett
erzeugen.
Eine Relation ohne komplexe Attribute heißt Relation in erster Normalform
(1NF).
Leider kann man nicht jede NFNF-Relation (Non-First-Normal-Form) verlustfrei
in eine 1NF-Relation überführen. Wenn es in der obigen Relation eine zweite
Person Wolfgang mit anderen Hobbies ({Fahrrad,Judo}) gäbe, könnten
beide nach der Normalisierung nicht mehr unterschieden werden. Hier müsste
wieder ein zusätzlicher (künstlicher) Identifikator eingeführt werden.
ID
1
1
1
2
2
3
3
Name
Wolfgang
Wolfgang
Wolfgang
Wolfgang
Wolfgang
Sonja
Sonja
Hobby
Akkordeon
Fahrrad
Flöte
Fahrrad
Judo
Flöte
Ballett
Objektorientierte Schemata sind i. Allg. nicht in 1NF. Es gibt aber auch RDBS, die
NFNF-Relationen unterstützen. Man braucht dann allerdings weitere relationale
Operatoren wie FOLD und UNFOLD zum Transformieren von NFNF-Relationen
in 1NF-Relationen und umgekehrt.
!"#$%
&E~
2
✎
String wird in vielen Sprachen wie C++ als komplexer Datentyp (Array) behandelt!
27
Draft (2. März 2000)
✎
?°
3.2 Überführung eines ER-Modells in ein relationales Schema
ER-Modelle sind wesentlich ausdruckskräftiger als Relationenschemata, da zwischen Entities und Beziehungen unterschieden wird.
Daher sollte man immer zunächst ein ER-Modell erstellen und dieses dann nach
„Schema F“ in ein Relationenschema transformieren.
3.2.1 „Schema F“
1. Jeder Entitytyp ± mit Attributen ª H JBABABABJ™ª K und den zugehörigen Domänen
ˆ H JBABABACJ1ˆ K wird auf das Relationenschema ±Š¨£ª H «²ˆ H JBABACA1JIª K «²ˆ K ¯ abgebildet.
2. ISA-Beziehungen ³ isa ± können entweder durch Hinzunahme aller Attribute oder nur der Primärschlüsselattribute von ± zu ³ realisiert werden. Im
ersten Fall hat man zwar mehr Daten als im zweiten, man spart sich aber
später eine Joinoperation um in ³ auch an die von ± geerbten Nichtschlüsselattribute zu gelangen.
Eine dritte Realisierungsmöglichkeit ist es, für eine gesamte ISA-Hierarchie
nur eine einzige Tabelle zu definieren. Diese enthält die Attribute der Basisklasse sowie aller Subklassen. Nichtdefinierte Attributwerte werden mit
Null initialisiert.
3. Ein Relationship † zwischen Entity-Typen ± H JBABABABJ¢± K wird durch ein Relationenschema †©¨ACABAž¯ dargestellt, das aus allen Primärschlüsselattributen aller
Entitytypen ± H JBABABA¢J1± K besteht. Gleiche Attributnamen werden dabei geeignet umbenannt. Eigene Attribute der Relationship † werden zum Relationenschema hinzugenommen.
Draft (2. März 2000)
28
Beispiel
Professor
Name
Dienstzimmer
Tel
0..* Student
0..*
Name
Matrikelnummer
prüft
Datum
Fach
Anmerkung: Der bessere Primärschlüssel von Student wäre Matrikelnr.
Ich möchte aber im Folgenden auch zeigen, wie man mit gleichbenannten Attributen unterschiedlicher Bedeutung umgeht.
Datenbankschema
Professor: Name, Dienstzimmer, Tel
prüft:
PName, SName, Datum, Fach
Student:
Name, Matrikelnr
SQL-Schema
CREATE TABLE Professor
(Name
VarChar(20) not null,
Dienstzimmer VarChar(5),
Tel
integer,
PRIMARY KEY (Name)
)
Anmerkung: Der Primärschlüssel (primary key) einer Tabelle sollte immer definiert werden.
CREATE TABLE Student
(Name
VarChar(20) not null,
Matrikelnummer VarChar(10) not null,
PRIMARY KEY (Name),
UNIQUE (Matrikelnr)
)
Hier wurde neben der Primary-Key-Bedingung noch eine weitere (vom System zu
überprüfende) Integritätsbedingung angegeben. Jede Matrikelnummer muss eindeutig (unique) sein, d. h., zwei Studenten dürfen nicht dieselbe Matrikelnummer
haben. Insbesondere bedeutet das, dass Matrikelnr ein Schlüsselkandidat –
und zwar der bessere! – ist.
29
Draft (2. März 2000)
CREATE TABLE prueft
(PName
VarChar(20) not null,
SName
VarChar(20) not null,
Datum
datetime[YY:MI] not null,
Fach
VarChar(20) not null,
PRIMARY KEY (PName,SName,Datum,Fach),
FOREIGN KEY (PName) REFERENCES Professor (Name),
FOREIGN KEY (SName) REFERENCES Student (Name)
)
Bei der Überführung eine Relationship in eine Tabelle werden zwei Fremdschlüssel-Integritätsbedingungen definiert (Fremdschlüssel = foreign key). Diese besagen, dass ein Tupel „Professor A prüft Student B“ nur existieren kann, wenn es
sowohl den Professor A in der Tabelle Professor als auch den Studenten B
in der Tabelle Student gibt. Das heißt, Student B kann beispielsweise nur
gelöscht werden, wenn zuvor das obige Prüfungstupel ebenfalls gelöscht wurde
referenzielle Integrität = alle Fremdschlüsselbedingungen werden erfüllt).
Foreign Keys sollten bei „Relationship-Tabellen“ normalerweise immer definiert
werden, wenn nicht triftige Effizienzgründe dagegen sprechen.
3.2.2 Optimiertes „Schema F“
Das vorgestellte Verfahren zur Überführung von ER-Diagrammen in Relationenschemata funktioniert für jedes ER-Diagramm, d. h., für beliebige Entitytypen und
beliebige Relationen. Allerdings ist das Verfahren für 1:n-, n:1- und 1:1-Beziehungen nicht optimal, da man in beiden Fällen die spezielle „Relationshiptabelle“
einsparen kann ( D Join-Einsparung).
1:n/n:1-Beziehungen
Person
0..*
Lieblingsspeise
Name
Alter
1 Speise
Name
Joule
Datenbankschema
Person: Name, Alter, Lieblingsspeise(Name)
Speise: Name, Joule
Draft (2. März 2000)
30
SQL-Schema
CREATE TABLE Person
(Name
VarChar(20) not null,
Alter
integer,
Lieblingsspeise VarChar(20) not null,
PRIMARY KEY(Name),
FOREIGN KEY (Lieblingsspeise) REFERENCES Speise(Name)
)
CREATE TABLE Speise
(Name VarChar(20) not null,
Joule integer,
PRIMARY KEY (Name)
)
"! #$%
&E°
?´
✎
✎
1:1-Beziehungen
Angestellter
1 Personalakte
1
Persnr
..
.
Persnr
..
.
1:1-Beziehungen kann man vollständig eliminieren, indem man einfach alle Attribute der beiden zugehörigen Entitytypen in einer Tabelle gemeinsam ablegt. Einen
der beiden Primärschlüssel verwendet man als Primärschlüssel der gemeinsamen
Tabelle. Das andere Primärschlüsselattribut kann komplett entfernt werden, wenn
es sich um ein speziell definiertes Identifikationsattribut handelt, anderenfalls behält man es bei und definiert es als unique(<Attribut>).
Optionale Beziehungen
A
0..*
0,1
B
Erweitere A um den anderen Fremdschlüssel (wie im Fall 1:n). Der Fremdschlüssel darf dabei auch den Wert Null annehmen (im Gegensatz zum Fall 1:n).
Im obigen Beispiel mit der Lieblingsspeise wird Lieblingsspeise VarChar(20) not null durch Lieblingsspeise VarChar(20) ersetzt.
31
Draft (2. März 2000)
A
0,1
0,1
B
Erweitere A oder B um den anderen Fremdschlüssel. Der Fremdschlüssel darf
auch den Wert Null annehmen.
A
0,1
1
B
Erweitere A um den anderen Fremdschlüssel. Der Fremdschlüssel darf nicht Null
sein (da es zu jedem µh¶`ª ein ·­¶¹¸ geben muss). Man beachte allerdings, dass
· ¶º¸ auch ohne µh¶`ª existieren kann.
ER }
Rel-Matrix
Die Abbildungen einer ER-Beziehung
A
r
B
auf Relationenschemata abhängig von den Multiplizitäten kann man mit Hilfe
einer Matrix zusammenfassen.
» 0
¸
zu µh¶[ª gibt es
½
»
1
=1
1
soviele ·¼¶º¸
ª
½
1
=1
»
»
0
1
R
zu ·­¶º¸
gibt es
soviele
µa¶`ª
R
foreign key in ª references ¸
foreign key in ¸ references ª
foreign key, not null
Relationship als eigene Relation
(+ Zusatzbedingungen)
Komplexe Attributtypen
Komplexe Attributtypen, wie set<Person>, list<Person> etc., werden
durch die Einführung zusätzlicher Entitytypen und zusätzlicher Beziehungen eliminiert und wie zuvor behandelt.
Draft (2. März 2000)
32
<
=
Auto
<
Auto
Auto
4
Rad
Räder: Rad[4]
=
1
0..*
Rad
{Ein Auto hat 4 Räder}
Person
0,1,2
Kinder
Name: string
0..*
<
Person
Name: string
Kinder: list<Person>
=
Reduktion der Anzahl der Relationschemata
Die Überführung eines ER-Modells in ein relationales Schema liefert unter Umständen mehrere Relationen mit gemeinsamen Schlüsselkandidaten. Derartige Relationen können zu einer Relation zusammengelegt werden D Joinvermeidung.
Wenn „† H ¨¡ª H JBABABABJ™ª­¾¼¯ „ und † |¨Y¸ H JBABABA¢J1¸ „ K ¯ den gemeinsamen Schlüsselkandiª H JBABABABJ™ª­¾¼…ŠÁ ¸ H JBABACA1J1¸ K … haben, „ dann kann man
daten H JBABABABJ¢¿š…À‡
„† H und †/ durch eine neue Relation † O mit
„ den Attributen ª H JCABABA¢JIª­¾¼…ƒ
¸ H JBACABA1J¢¸ K … und dem Schlüsselkandidaten H JBACABA1J¢ ¿ … ersetzen.
Abteilung
Name
Nr
Hardware 11
Software 13
Abteilungsleiter
Nr Leiter
11 ’Müller, Hans’
13 ’Meier, Schorsch’
D
Abteilung
Nr Name
Leiter
11 Hardware ’Müller, Hans’
13 Software ’Meier, Schorsch’
3.3 Die Relationale Algebra und SQL
Im Folgenden werden wir die klassische Lieferanten-DB als „running example“
nehmen.
33
Draft (2. März 2000)
0..n Lieferant
0..*
Ware
Wnr
Typ
Bezeichnung
liefert
Preis
Lieferzeit
Lnr
Name
Adresse
Das zugehörige Relationenschema sieht wie folgt aus:
Ware
Wnr
Typ
Bezeichnung
PRIMARY KEY (Wnr)
Lieferant
Lnr
Name
Adresse
PRIMARY KEY (Lnr)
liefert
Wnr
Lnr
Preis
Lieferzeit
PRIMARY KEY (Wnr,Lnr)
FOREIGN KEY (Wnr) REFERENCES Ware
FOREIGN KEY (Lnr) REFERENCES Lieferant
Wie bereits bekannt ist, sind Relationen Teilmengen des kartesischen Produktes
der zugehörigen Domänen.
Beispiele
Lieferant
Lnr Name
1
’Maier’
2
’Müller’
3
’Maier’
Ware
Wnr
Typ
Draft (2. März 2000)
Adresse
’Königsbrunn’
’Königsbrunn’
’Augsburg’
Bezeichnung
34
1
2
3
4
.
.
.
liefert
Lnr
1
1
1
2
’CPU’
’CPU’
’CPU’
Graphikkarte
Wnr
1
2
3
3
"Â ÃÄ$Å%ÆÇÈÉÅÊ&ËÃÌEÍ
ÆÇÈÉÅÊËÃÌ?Î
Preis
50
300
150
170
’Pentium 200’
’Pentium II 330’
’Celeron 330’
’Matrox G200’
Lieferzeit
1
2
7
4
✎
✎
Unter einer relationalen Algebra versteht man eine Menge von relationalen
Operationen, die eine oder mehrere Relationen (Tabellen) wieder auf Relationen
abbilden.
Die Algebra-Eigenschaft, dass die Ergebnisse relationaler Operationen immer Relationen sind, wird auch als Abgeschlossenheit bezeichnet. Die Abgeschlossenheit
hat zur Folge, dass nacheinander beliebig viele relationale Operationen auf eine
Tabelle angewendet werden können.
3.3.1 Die Identität
Die einfachste relationale Operation ist die Identität ϡЮѲÒÓ
Ô als Ganzes zurückliefert:
Ò
, die jede Relation
Ï£Ð²Õ ÔŸÖ×Ô
In SQL2 geschieht dies mit Hilfe eines speziellen Select-Befehls.
select distinct * from Lieferant
select distinct * from <komplexer relationaler Ausdruck>
select distinct * from < Ô > Ø table <r>, wenn Ô duplikatfrei
Man beachte, dass der select-Befehl Duplikate nur dann automatisch entfernt,
wenn man select distinct schreibt. Anderenfalls (d. h. bei select oder
select all) kann das Ergebnis Duplikate enthalten. Das heißt, SQL realisiert
eine Multimengen-Semantik. Im Falle von Basis-Relationen (wie z. B. Lieferant) ist die Angabe von distinct allerdings nicht notwendig, da derartige
Relationen immer ohne Duplikate gespeichert werden.
35
Draft (2. März 2000)
3.3.2 Die Projektion
Die Projektion dient dazu, bestimmte Spalten aus einer beliebigen (d. h. gespeicherten oder berechneten Tabelle) zu selektieren.
Wenn Ò©Õ£ÙwÚCÛBÜBÜBÜ¢ÛIÙ­Ý Ö eine Relation ist und Þqß-ÚCÛBÜBÜBÜ¢Û1ßàqá eine Teilmenge der Attribute, dann ist âãåä&æèç^ç^ç æ ã¬éê¤ëiì diejenige Tabelle, die aus Ò entsteht, wenn man alle
übrigen Spalten aus Ò entfernt. Man beachte: dabei entstehende Duplikate müssen
ebenfalls entfernt werden.
Beispiel
Ware
1 ’CPU’
2 ’CPU’
7 ’RAM’
9 ’RAM’
â
’Pentium 200’
’Celeron 300’
’FP 16MB’
’SD100 16MB’
Typ
Õ Ware Ö
’CPU’
’RAM’
Man kann die obige Definition der Projektion sogar noch erweitern: Jede Spalte
der Ergebnisrelation wird mit Hilfe jeweils einer Funktion aus den Attributwerten
von beliebig vielen (d. h. 0, 1 oder mehreren) Attributen der Ursprungsrelation
berechnet: â²íîä¡ïíið æñIæ íóòYô ê íõ&ïíö ì ÕYÒ Ö
â
æ
’Sonderangebot’ ’Billig’+Typ
Õ Ware Ö
’Sonderangebot’ ’BilligCPU’
’Sonderangebot’ ’BilligRAM’
In SQL wird die Projektionsliste direkt nach dem Schlüsselwort select angegeben.
select distinct Typ from Ware
select distinct ’Sonderangebot’, ’Billig’||Typ
from Ware
Anmerkung: Die Verknüpfung (Konkatenation) zweier Zeichenketten erfolgt in
SQL mit dem Verknüpfungsoperator || (und nicht wie sonst mit +).
Wie bereits bekannt ist, darf in der Projektionsliste auch * stehen, als Abkürzung
für die Liste aller Attribute einer Relation.
Bisher habe ich meist eine abkürzende SQL-Schreibweise verwendet. Genaugenommen muss man zu jeder Relation in der From-Klausel auch noch einen Tupelbezeichner definieren. Den Tupelbezeichner kann man sich als Variablennamen
vorstellen, der der Reihe nach alle Tupel der zugehörigen Relation durchläuft. In
SQL ist allerdings eher die Auffassung üblich, dass der Tupelbezeichner lediglich
ein Alias-Name für eine Relation ist.
Draft (2. März 2000)
36
select
select
select
select
W.Typ from Ware W
W.* from Ware as W // as ist optional
’Sonderangebot’, ’Billig’||W.Typ from Ware W
’Bruttopreis’, lief.Preis*1.16 from liefert lief
Man kann sogar die Attributnamen mit as umbenennen:
select W.T from Ware as W(Nr, T, Bez)
Defaultmäßig wird der Relationenname selbst als Tupelbezeichner verwendet,
auch wenn dies formal nicht ganz sauber ist.
Ø
select Typ from Ware
select Ware.Typ from Ware Ware
Wenn die Attributnamen der Projektionsliste völlig eindeutig sind (wie in unserem
bisherigen Beispielen), kann man auf den Tupelbezeichner sogar verzichten.
3.3.3 Die Selektion
Während die Projektion dazu dient, bestimmte Spalten einer Tabelle zu selektieren
(und weiterzuverarbeiten), dient die Selektion dazu, bestimmte Zeilen einer Tabelle zu selektieren. Bei der Selektion wird für jedes Tupel ein boolesches Prädikat
(welches von den Attributen der zugehörigen Relation abhängt) ausgewertet.
÷
Õ Ware Ö
Typ=’RAM’
7 ’RAM’ ’FP 16 MB’
9 ’RAM’ ’SD100 16 MB’
÷
ø
Typ=’RAM’ Bezeichnung like ’SD%’
Õ Ware Ö
9 ’RAM’ ’SD100 16 MB’
SQL unterstützt folgende boolschen Operatoren:
=, <=, >, >= und <> sowie OR, AND, NOT, IS [NOT] TRUE/FALSE/UNKNOWN/NULL, [NOT] BETWEEN ÜBÜBÜ AND ÜBÜBÜ und LIKE.
Daneben werden auch noch Operatoren angeboten, die auf ganzen Tabellen arbeiten: [NOT] IN, MATCH, ALL, ANY, SOME, EXISTS, UNIQUE.
Diese Operatoren werden Sie später kennenlernen.
37
Draft (2. März 2000)
3-wertige Logik
Da Tabellen i. Allg. auch den Wert NULL enthalten können, realisiert SQL eine
sogenannte 3-wertige Logik (three-valued logic).
In dieser gibt es die drei Wahrheitswerte true (t), false (f) und unknown(u) mit folgenden Wahrheitsmatrizen:
AND
t u f
t
u
f
t u f
u u f
f f f
OR
t
u
f
t u f
NOT
t
t t t
t u u
t u f
t
u
f
f
u
t
Außerdem müssen Arithmetikoperatoren, Vergleichsoperatoren etc. mit NULL
umgehen können, wobei NULL als unbekannter und nicht als undefinierter Wert
interpretiert wird:
5+NULL=NULL, 5>NULL
ù
UNKNOWN etc.
Beispiel
Es gebe drei Attribute A=3, B=4 und C=NULL.
Dann gilt:
A>B AND B>C
A>B OR B>C
A<B OR B<C
NOT(A=C)
ù
ù
ù
ù
false
unknown
true
unknown
Achtung: X IS FALSE ist nicht das Gegenteil von X IS NOT TRUE. X IS
NOT TRUE heißt X IS FALSE OR X IS UNKNOWN.
Anmerkung: Wenn man ausschließlich mit Attributen arbeitet, deren Domänen als
NOT NULL deklariert wurden, reduziert sich die dreiwertige Logik von SQL auf
die klassische zweiwertige Logik.
✎
✎
"Â ÃÄ$Å%ÆÇÈÉÅÊ&ËÃÌEÎ
ÆÇÈÉÅÊËÃÌ?úüûdýBÅþɟÿBÿ
3.3.4 Vereinigung, Durchschnitt, Differenz
Relationen sind Mengen. Es können daher die Vereinigung, der Durchschnitt oder
die Differenz zweier Relationen gebildet werden. Dabei muss allerdings darauf
Draft (2. März 2000)
38
geachtet werden, dass die zugehörigen Relationen dieselben Attribute (Attributnamen und Attributdomänen) haben.
Ò Õ¡ÙwÚ Ñ ÚBÛCÜBÜBÜBÛIÙ Ý Ñ Ý Ö Õ¡ÙwÚ ÑfÚCÛBÜBÜCÜBÛI٭݊ÑÝ Ö
Ò Õ¡ÙwÚ Ñ ÚBÛCÜBÜBÜBÛIÙ Ý Ñ Ý Ö Õ¡ÙwÚ ÑfÚCÛBÜBÜCÜBÛI٭݊ÑÝ Ö
Ò Õ¡ÙwÚ Ñ ÚBÛCÜBÜBÜBÛIÙ Ý Ñ Ý Ö Õ£ÙwÚ ÑfÚCÛBÜBÜCÜ1ÛIÙ Ý®ÑiÝ Ö
In SQL gibt es zu diesem Zweck die Operationen union (mit Duplikatelimination), union all (ohne Duplikatelimination), intersect, intersect
all, except und except all.
Alle CPU und RAM-Bausteine:
(select * from Ware where Typ=’CPU’)
union
(select * from Ware where Typ=’RAM’)
Alle Lieferanten, deren Name nicht mit „M“ anfängt.
(select * from Lieferant)
except
(select * from Lieferant where Name like ’M%’)
Daneben gibt es noch die Möglichkeit, nur bestimmte gemeinsame Attribute zweier Relationen zu berücksichtigen und die anderen Spalten zu eliminieren.
A union all corresponding by (x,y) B
=
(select x,y from A) union all (select x,y from B)
Wenn by (x,y) weggelassen werden würde, würden alle gemeinsamen Attribute von A und B verwendet werden.
" ÃÄ$Å%ÆÇÈÉÅÊ&ËÃÌEúüûdýBÅþɟÿBÿ
ÆÇÈÉÅÊËÃÌ
✎
✎
3.3.5 Kartesisches Produkt und Join
Zwei Relationen können mit Hilfe des kartesischen Produktes ( ) verknüpft werden.
Lieferant liefert
Lnr
1
1
1
1
Name
’Maier’
’Maier’
’Maier’
’Maier’
Adresse
’Königsbrunn’
’Königsbrunn’
’Königsbrunn’
’Königsbrunn’
39
Lnr
1
1
1
2
WNr
1
2
3
3
Preis
50
300
150
170
Lieferzeit
1
2
7
4
Draft (2. März 2000)
2
2
2
2
3
3
3
3
’Müller’
’Müller’
’Müller’
’Müller’
’Maier’
’Maier’
’Maier’
’Maier’
’Königsbrunn’
’Königsbrunn’
’Königsbrunn’
’Königsbrunn’
’Augsburg’
’Augsburg’
’Augsburg’
’Augsburg’
1
1
1
2
1
1
1
2
1
2
3
3
1
2
3
3
50
300
150
170
50
300
150
170
1
2
7
4
1
2
7
4
Mit Hilfe des kartesischen Produktes, der Selektion und der Projektion kann nun
z. B. bestimmt werden, wer Waren innerhalb von einem Tag liefern kann.
liefert Ö&Ö ,
wobei L ein Tupelbezeichner für Lieferant und lief ein Tupelbezeichner
für liefert sei.
â
æ
Name Adresse
Lnr
1
//
1
//
1
1
2
2
2
//
2
3
3
3
3
Õ÷
L.Lnr=lief.Lnr AND Lieferzeit=1
Name
Adresse
Õ Lieferant Lnr WNr
1
///////////
’Maier’ ’Königsbrunn’
////////////////// 1// 2//
///////////
’Maier’ ’Königsbrunn’
//////////////////// 1// 3//
’Maier’ ’Königsbrunn’ 2
3
’Müller’ ’Königsbrunn’ 1
1
’Müller’ ’Königsbrunn’ 1
2
’Müller’ ’Königsbrunn’ 1
3
///////////
’Müller’
// ’Königsbrunn’
//////////////////// 2// 3//
’Maier’ ’Augsburg’
1
1
’Maier’ ’Augsburg’
1
2
’Maier’ ’Augsburg’
1
3
’Maier’ ’Augsburg’
2
3
’Maier’
’Königsbrunn’
1
////////
â
÷
÷
Preis
50
300
/////
150
/////
170
50
300
150
170
/////
50
300
150
170
Lieferzeit
1
2//
7//
4
1
2
7
4//
1
2
7
4
L.Lnr lief.Lnr
Lieferzeit 1
æ
Name Adresse
In SQL wird das kartesische Produkt beliebig vieler Relationen einfach dadurch
gebildet, dass mehrere Relationen (evtl. zusammen mit Tupelbezeichnern) in die
From-Klausel geschrieben werden:
select L.Name, L.Adresse
from Lieferant L, liefert lief
where L.Lnr=lief.Lnr and lief.Lieferzeit=1
Weitere Beispiele
Welche Waren liefert Maier aus Königsbrunn?
Draft (2. März 2000)
40
select W.Typ, W.Bezeichnung
from Lieferant L, liefert lief, Ware W
where L.Lnr=lief.Lnr and lief.Wnr=W.Wnr and
L.Name=’Maier’ and
L.Adresse like ’%Königsbrunn%’
Wer liefert welche Waren billiger als Maier aus Königsbrunn?
select L.Name, L.Adresse,
W.Typ, W.Bezeichnung,
lief.Preis, liefM.Preis
from
// Ware der anderen Lieferanten
Lieferant L, liefert lief, Ware W,
// Ware von Maier (ohne Warenbezeichnung und -typ)
Lieferant LM, liefert liefM
where // Lieferant Maier
LM.Name=’Maier’ and
LM.Adresse like ’%Königsbrunn%’ and
// liefert diese Waren:
LM.Lnr = LiefM.Lnr and
// Die anderen
L.Lnr<> LM.Lnr and
// liefern dies:
L.Lnr=lief.Lnr and W.Wnr=W.Wnr and
// Dieselbe Ware
lief.Wnr=liefM.Wnr and
// kostet weniger als bei Maier
lief.Preis<liefM.Preis
Man sieht, dass die Verwendung von Tupelbezeichnern unerlässlich ist, wenn man
ein und dieselbe Relation mehrfach in der From-Klausel verwenden muss.
"Â ÃÄ$Å%ÆÇÈÉÅÊ&ËÃÌ
ÆÇÈÉÅÊËÃÌ
✎
✎
Join-Operationen
Das kartesische Produkt zusammen mit der Selektion reicht – von einem rein mathematischen Standpunkt aus gesehen – aus, um die Verknüpfung von zwei oder
mehreren Tabellen zu beschreiben. In der Realität machen kartesische Produkte
allerdings Probleme, da die Zwischenergebnisse sehr groß werden können. Die
Anzahl der Elemente (Mächtigkeit) einer Menge bezeichnet man mit oÜ . Für Relationen Ò­ÚCÛBÜBÜCÜ1Û1Ò/Ý gilt: ^ҭړÜBÜBÜºÒ Ý × èÒ ÚqÜBÜCÜèÒ/Ý
41
Draft (2. März 2000)
Wenn wir z. B. 100 Lieferanten, 1000 Waren und 50000 liefert-Tupel haben,
besteht das kartesische Produkt der fünf Relationen des letzten SQL-Beispiels aus
!
"
#
$#
!
"
# ×&%
$ ñ
"' Ú
!)(
Tupeln. In Worten: 25 Billiarden Tupel. Wenn unser Rechner
Tupel pro Sekunde abarbeiten kann, benötigt er also zur Beantwortung der gestellten Frage
% "* $+ Sekunden = % "', Û- Jahre = 792,75 Jahre.
Aus diesem Grund wurden die sogenannte Joinoperation eingeführt, die im wesentlichen kartesische Produkte gefolgt von speziellen Selektionen und Projektionen sind. Diese Spezialfälle können meist sehr effizient bearbeitet werden.
Prädikatjoin
Die allgemeinste (und i. Allg. ineffizienteste) Joinoperation ist der Prädikatjoin:
Ò/.021 Ñ ×÷ 1²ÕPÒ3 Ö
Dabei ist 4 ein Prädikat (wie 6
Ù 587:9`ß<;=" ), welches sich auf beliebige Attri
bute von Ò und abstützt.
Equijoin
Wenn das Prädikat lediglich je ein Attribut (oder je eine Menge von Attributen) der
beiden Relationen Ò und auf Gleichheit testet, spricht man von einem Equijoin:
Ò/.0 ëfç í > ç ? Ñ ×:÷ ëfç í > ç ? ÕYÒ@ Ö
Equijoins sind sehr effizient realisierbar und kommen sehr häufig vor (siehe letztes
SQL-Beispiel).
Die Komplexität beträgt AÕèÒB$CEDF'èÒG$H@ $CID#F' $H3 <Ergebnis> Ö .
Falls das Ergebnis klein ist, kann die letzte Größe vernachlässigt werden. Das
Ergebnis ist nur dann groß, wenn ein und derselbe Attributwert in sehr vielen
Tupeln vorkommt, wie z. B. Geschlecht: weiblich oder männlich. Falls
jedoch jedes Tupel der kleineren Relation im Durchschnitt nur einen Joinpartner
hat, ist das Ergebnis so groß wie die kleinere Relation, d. h. AÕ <Ergebnis> Ö$×
AÕ min Þ^ÒGoÛ# èá Ö 5:AÕJèÒG#$CID#F'èÒG Ö und AÕ $CEDF' Ö .
Insbesondere Schlüsselattribute kommen in einer Relation nicht mehrfach vor.
Das heißt, wenn z. B. eine Relation Ò über ein Schlüsselattribut (von Ò ) mit gejoint wird, gilt <Ergebnis> K .
✎
L*þÅÈMNPO*źþRQSMTqËÈVUwÄWN$ÊYXiÈjþÃUŸþRZ Ä*ÅÊW[qÇÈ]\2^`_¹ÅȁÌ*Åa^`b­ÉÌ*ÇÈþ \2Mc¹ËÊÅÊîÅÈTqÉRd$È]\#e
Unter der Annahme, dass die Ergebnisgröße bei der Bestimmung der Zeitkomplexität vernachlässigt werden kann, ergeben sich beispielsweise folgende Laufzeitunterschiede:
Angenommen èÒG
× × $(
Draft (2. März 2000)
42
$ Úgf ! (
Tupel/sec
^ÒG# ×
Û
h
Ûi"-' Konstante1 Tage kartesisches Produkt
^ ÒG log ^ ÒG$H3 $$CID#Fj × $( klH $( k × % !)( Û $)( Tupel m sec
h
% Konstante2 Sekunden Join
Naturaljoin
Der Naturaljoin ist ein Equijoin über gleichbenannte Attribute der Relationen R
und S. Wenn Ò©Õ¡ÙwÚCÛBÜBÜCÜBÛIÙon­Û1ß-ÚCÛBÜBÜCÜ1Û1ß à Ö und Õp7­ÚCÛBÜBÜBÜ¢Û7 ÝÛ1ß-ÚCÛBÜBÜBÜ¢Û1ß à Ö dann:
Ò/.0 Ñ × â íîä æ^çèç^ç æ íq æã ä æèç^ç^çæã¬éBæ ? ä æ^çèç^çæ ? q ÕPÒ:.0 ëfç ãsr > ç ãsr Ö
Semijoin
Der Semijoin ist ein Spezialfall des Naturaljoins, der nur die Attribute von R als
Ergebnis liefert:
Ò@t Ñ × â í äYæ^ç^çèçæ íq æ ãåä&æèç^çèç æã€é ÕPÒ=.0 Ö
Der Semijoin ist eine spezielle Selektion: Aus
wählt, die in einen Joinpartner haben.
Ò
werden diejenigen Tupel ausge-
Effizienz
Der Naturaljoin lässt sich genauso effizient wie der Equijoin implementieren (Er
ist ja nichts weiter als ein Equijoin mit anschließender Projektion). Der Semijoin
kann sogar noch etwas effizienter implementiert werden, da die Tupel von nicht
weiterverarbeitet werden müssen.
Optimierung
In SQL schreibt man Joins meist nicht explizit hin, sondern überlässt es den Optimierern, eine möglichst optimale Joinoptimierung des kartesischen Produktes
Ý
vorzunehmen. Dies ist allerdings sehr schwierig, da es AÕ`uwv Ö × AÕ`u Ö mögli
!
% , v × ,Sk %xSx ). Es gibt Meche Joinvarianten für u Relationen gibt ( "sv ×
Ý
Ú`y × $ %)z ,
thoden eine sehr gute Joinreihenfolge mit der Komplexität AÕ % Ö ( %
$
% f{y ×
zx "|-}k ) zu bestimmen. Für u~;
ist auch das noch zuviel – vor allem, wenn Anfragen interaktiv ausgewertet werden sollen. Dafür gibt es heuf $ f × ! ,
ristische Verfahren zur Joinoptimierung mit der Komplexität AÕ`u Ö (
% f ×:z ). Allerdings können diese Verfahren normalerweise nicht auf beliebige, sondern nur auf spezielle zu joinende Relationen angewendet werden.
Explizite Joins in SQL
Da es sehr schwierig ist, eine optimale Joinreihenfolge automatisch zu bestimmen,
ist es in SQL auch möglich, Joins in der FROM-Klausel explizit anzugeben.
43
Draft (2. März 2000)
Kartesisches Produkt: (cross join)
select L,A,P,Z
from
(Lieferant cross join liefert)
as Lcl (Lnra, L, A, Lnrb, Wnr, P, Z)
Anmerkung: Bei der expliziten Angabe des zu verwendenden Joinoperators wird
normalerweise immer der Alias-Operator as verwendet, um das Joinergebnis zu
benennen. Hier heißt das, dass sowohl in der Select-Klausel als auch in der
where-Klausel nur noch auf die (temporär erzeugte) Tabelle Lcl zugegriffen
werden kann, nicht aber auf die ursprünglichen Tabellen Lieferant und liefert.
Naturaljoin
select Name, Preis
// select lieferbar.Name, lieferbar.Preis
from (Lieferant natural join liefert) as lieferbar;
Hier verschattet die (temporär erzeugte) Relation lieferbar die ursprünglichen Tabellen Lieferant und liefert.
Anmerkung: Wenn es keine gemeinsamen Attribute gibt, degeneriert der Naturaljoin zum Kreuzprodukt.
Prädikatjoin
select Name, Preis
from ( Lieferant join liefert
on Lieferant.Lnr = liefert.Lnr )
as lieferbar;
h
select * liefert als Ergebnis zwei Lnr-Spalten, da beliebige Joinbedingungen angegeben werden können (z. B. Lieferant.Lnr < Liefert.Lnr). Das heißt, in den beiden Lnr-Spalten können pro Tupel durchaus
unterschiedliche Werte stehen.
Equijoin
select Name, Preis
from ( Lieferant join liefert using (Lnr) )
h
select * liefert als Ergebnis eine Lnr-Spalte, da beide Spalten für jedes
Tupel immer denselben Wert enthalten.
✎
✎
"Â ÃÄ$Å%ÆÇÈÉÅÊ&ËÃÌ
ÆÇÈÉÅÊËÃÌ1ÿ
Draft (2. März 2000)
44
Outer Joins
Elemente einer Tabelle Ò , die keinen Joinpartner in einer Tabelle finden, erscheinen nicht im Ergebnis von Ò@.0 . Manchmal benötigt man allerdings alle
Elemente der Tabelle Ò , unabhängig davon, ob es einen passenden Joinpartner
gibt oder nicht. Dies ist mit Hilfe der sogenannten Outer-Joins möglich.
Der Left-Outer-Join sorgt dafür, dass die linke Tabelle vollständig erhalten bleibt,
der Right-Outer-Join, dass die rechte Tabelle erhalten bleibt und der Full-OuterJoin, dass beide erhalten bleiben.
Der Natural-Left-Outer-Join, beispielsweise, ist wie folgt definiert:
select * from R NATURAL LEFT JOIN S
Ø (Pseudo-SQL)
( select * from R NATURAL JOIN S )
union all
( select *, NULL, ÜBÜBÜ , NULL from R
where * not in (select R.* from R NATURAL JOIN S) )
Beispiel
R
Name
Waren
Maier Lampen
Müller Rechner
R .0 S
Maier Lampen
S
Name Tel
Maier 123
Huber 234
123
R .0 left S
Maier Lampen 123
Müller Rechner Null
R .0 right S
Maier Lampen
Huber Null
R .0 full
Maier
Müller
Huber
123
234
S
Lampen 123
Rechner Null
Null
234
Daneben gibt es noch den Union Join, der überhaupt keine Joinpartner sucht, sondern nur NULLs als Joinpartner einsetzt.
45
Draft (2. März 2000)
R union join S
Maier Lampen
Müller Rechner
Null
Null
Null
Null
Null
Null
Maier
Huber
Null
Null
123
234
Zusammenfassung
SQL unterstützt folgende expliziten Joins:
CROSS JOIN
JOIN
LEFT JOIN
RIGHT JOIN
FULL JOIN
UNION JOIN
=
=
=
=
INNER JOIN (Prädikatjoin)
LEFT OUTER JOIN
RIGHT OUTER JOIN
FULL OUTER JOIN
NATURAL JOIN = NATURAL INNER JOIN (Naturaljoin)
NATURAL LEFT/RIGHT/FULL JOIN
(ohne ON oder USING-Klausel)
Kreuzprodukt und Inner Join werden nur benötigt, um dem Optimierer Arbeit
abzunehmen. In einem ersten Schritt ist die Verwendung dieser Operatoren daher
meist unwichtig. Outer Join und Union Join sind dagegen echte Erweiterungen,
die im Zusammenhang mit Nullwerten stehen.
3.3.6 Division
Der Divisionsoperator dient dazu, allquantifizierte Fragen ( ÜBÜCÜ gilt für alle ÜCÜBÜ )
zu beantworten. Er ist im wesentlichen die Umkehroperation des Kreuzproduktes
( ÕYÒ@ ր“× Ò ).
Der Divisionsoperator € ist wie folgt definiert:
Es sei Ù × Þ|Ù Ú ÛBÜBÜBÜ¢ÛIÙ
gehören. Dann gilt:
Ýá
die Menge derjenigen Attribute von
Ò €= Ñ × â í ÕYÒ Ö â í Õ&Õ¡â í ÕYÒ Ö Ö Ò Ö
Beispiel
liefert
Lnr Wnr
1
1
1
2
Draft (2. März 2000)
Ware
Wnr
1
2
46
Ò
die nicht zu 1
2
2
3
1
2
3
Welcher Lieferant liefert alle Waren?
Ù × Þ
Lnr Û Wnr á Þ Wnr á
× Þ
Lnr á
Es gibt zwei Lieferanten:
â Lnr Õ liefert Ö
1
2
Wenn jeder alles liefern würde, hätten wir folgende Tabelle:
â Lnr Õ liefert Ö Ware
1
1
1
2
2
2
1
2
3
1
2
3
Allerdings liefert Lieferant 2 Ware 2 nicht:
Õ£â Lnr Õ liefert Ö Ware Ö liefert
2
3
Das heißt, Lieferant 2 liefert nicht alles:
â
Lnr
ÕÕ¡â
Lnr
Õ liefert Ö Ware Ö liefert Ö
2
Wenn man von der Liste aller Lieferanten diejenigen abzieht, die nicht alles liefern, bleiben nur diejenigen Lieferanten übrig, die alles liefern. Hier heißt das,
dass nur Lieferant 1 alles liefert:
â
Lnr
Õ liefert Ö â
Lnr
ÕÕ£â
Lnr
Õ liefert Ö Ware Ö liefert Ö
1
Realisierung in SQL
Der Divisionsoperator kann relativ effizient realisiert werden, er wird dennoch von
SQL nicht unterstützt. Das heißt, man muss ihn – z. B. analog zur Definition des
Divisionsoperators – durch andere Operatoren nachbilden. Die Realisierung des
47
Draft (2. März 2000)
Kreuzproduktes wäre allerdings zu teuer. Effizienter ist es, den exists-Operator
(Es gibt ein ÜBÜBÜ ) von SQL einzusetzen.
Man beachte, dass folgende Beziehung zwischen Für alle und Es gibt ein . . . gilt:
ƒ
Für alle ‚ gilt ÜBÜBÜ
ist gleichwertig zu
Es gibt kein ‚ , für das
‚4Մ‚ օ
†ˆ‡ ‚ † 4 Մ‚ Ö
ÜBÜBÜ
nicht gilt
Die Anfrage „Welcher Lieferant liefert alle Waren?“ kann also folgendermaßen
formuliert werden:
select distinct l1.Lnr from liefert l1
where <l1 liefert jede Ware>
Ø
select distinct l1.Lnr from Liefert l1
where <Es gibt keine Ware, die l1 nicht liefert>
Das heißt, wir müssen zunächst die Frage klären, welche Waren l1 nicht liefert.
select Wnr from liefert l2 where l2.Lnr = ‚
sagt uns, welche Waren der Lieferant ‚ liefert. Durch Differenzbildung erfahren
wir, welche Ware er nicht liefert:
(select W.Wnr from Ware W)
except
(select l2.Wnr from liefert l2 where l2.Lnr = ‚ )
Nun können wir den not-exists-Operator von SQL einsetzen, um unsere ursprüngliche Frage zu beantworten.
select distinct l1.Lnr from liefert l1
where not exists
( ( select W.Wnr from Ware W)
except
( select l2.Wnr from liefert l2
where l2.Lnr = l1.Lnr)
)
✎
✎
✎
"Â ÃÄ$Å%ÆÇÈÉÅÊ&ËÃÌ1ÿ
ÆÇÈÉÅÊËÃ̉ ý—ÅþɊ!Cÿ
‹
N$ÊɌ
Å \`UJ\dŽ
Å ÅþÊ Z$þÅÉ MNPO*źþRQaM`Ê&ÅaMÈN*ËʏMÈjÉþRQSMºÄ*þÊTqË\dþÅÈ]\#e
Draft (2. März 2000)
48
Man spricht hier von einer korrelierten Subanfrage (correlated subquery), da die
Hilfsanfrage in der Where-Klausel auf Variablen der übergeordneten Anfrage
(hier l1.Lnr) Bezug nimmt. In diesem Fall muss die Subanfrage für jeden Lieferanten einzeln ausgewertet werden. Eine nicht-korrelierte Subanfrage braucht
dagegen nur ein einziges Mal ausgewertet zu werden.
Andere Möglichkeiten der Realisierung in SQL
Die Anfrage
select * from liefert l2
where l2.Lnr = ‚ and
l2.Wnr = ‘
liefert ein Ergebnis genau dann wenn Lieferant ‚ die Ware ‘ liefert. Anderenfalls
ist das Ergebnis die leere Tabelle. Das heißt, wir können die Waren, die ‚ nicht
liefert, auch mit Hilfe einer korrelierten Subanfrage ermitteln.
select * from Ware W
where not exists
( select * from liefert l2
where l2.Lnr = ‚ and
l2.Wnr = W.Wnr
)
Und damit können wir unsere ursprüngliche Frage nach den Lieferanten aller Waren mittels zwei verschachtelter korrelierter Subanfragen formulieren:
select distinct l1.Lnr from liefert l1
where not exists
( select * from Ware W
where not exists
( select * from liefert l2
where l2.Lnr = l1.Lnr and
l2.Wnr = W.Wnr
)
)
Diese Art der Formulierung der Division in SQL ist sehr umständlich und auf den
ersten Blick unverständlich. Es gibt aber leider keine einfachere Möglichkeit, da
Allquantifizierung von SQL nicht unterstützt wird.
Dritte Möglichkeit der Realisierung in (Nicht-Standard-)SQL
In einigen Datenbanksystemen (z. B. in TransBase von TransAction Software
GmbH) ist es auch möglich, Mengen zu vergleichen: =, <>, <= (subset) etc.,
49
Draft (2. März 2000)
auch wenn dies im SQL2-Standard nicht vorgesehen ist. Damit kann die Frage,
welcher Lieferant alle Waren liefert relativ „natürlich“ formuliert werden:
select distinct *
from Lieferant L
where ( <Alle Waren, die L liefert> )
=
( <Alle Waren, die es gibt> )
Das heißt:
select distinct *
from Lieferant L
where ( select lief.Wnr from liefert lief
where lief.Lnr = L.Lnr )
=
( select W.Wnr from Ware W )
✎
✎
" ÃÄ$Å%ÆÇÈÉÅÊ&ËÃ̉üûdýBÅþÉwBÿ
ÆÇÈÉÅÊËÃÌp’ ûdý—ÅbþɟÿBÿ
3.3.7 Subanfragen (Subqueries)
In Abschnitt 3.3.6 wurden sogenannte Subanfragen zur Beantwortung bestimmter
Anfragen eingesetzt. Die Möglichkeit von Subanfragen sollen hier genauer untersucht werden. Achtung: Ich gehe im Folgenden davon aus, dass alle Tabellen in
Subanfragen keine Nullwerte enthalten. Die Behandlung von Nullwerten in diesem Zusammenhang würde den Vorlesungsrahmen sprengen.
Subanfragen können sowohl in SQL-Projektionslisten (Select-Klauseln) als
auch in SQL-Selektionslisten (Where-Klauseln) als auch in From-Klauseln stehen. Allerdings muss jede Subanfrage in einer Projektionsliste genau ein Element
als Ergebnis liefern.
Beispiel einer Projektionsliste mit Subanfragen
select
(select Autor from Autor where DOCID=5),
(select Titel from Titel where DOCID=5)
from dummy;
â“
Autor
êE”
DOCID=5
ê Autorìyìjæ “
Draft (2. März 2000)
Titel
êE”
DOCID=5
ê Titelìyì Õ dummy Ö
50
Hier sind Autor und Titel zwei Tabellen mit einem Attribut, das wie die Tabelle selbst heißt, und einem Primärschlüssel DOCID. Die Tabelle dummy enthält lediglich ein einziges Element für dessen Inhalt wir uns nicht weiter interessieren. Es wird aus syntaktischen Gründen benötigt, da in SQL2 immer eine
From-Klausel vorhanden sein muss. (In Oracle gibt es zu diesem Zweck standardmäßig die Dummy-Tabelle dual.)
Im Weiteren werden wir uns nicht mehr mit der Projektionsliste, sondern nur noch
mit der where-Klausel befassen.
Die in-Bedingung
Die aus der Mengenlehre bekannte ist-Element-von-Beziehung ( • ) gibt es auch
in SQL:
in
not in
=some
<>all
match
•
•–
Beispiel
Welcher Lieferant liefert den Artikel mit Warennummer 3?
select distinct L.Name
from Lieferant L
where L.Lnr in
( select lief.Lnr
from liefert lief
where lief.Wnr = 3)
Oder in Relationaler-Algebra-Notation:
â
L.Name
Õ÷ “
lief.Lnr
êE”
lief.Wnr
— ð1ê liefert
lief
ìyìYÕ Lieferant L Ö&Ö
Hier handelt es sich um eine nicht-korrelierte Subanfrage, die nur ein einziges Mal
berechnet werden muss. Man könnte die Anfrage allerdings auch mit Hilfe einer
korrelierten Subanfrage formulieren:
select distinct L.Name
from Lieferant L
where 3 in
( select lief.Wnr
from liefert lief
where lief.Lnr = L.Lnr)
oder (noch schlimmer):
select distinct L.Name
51
Draft (2. März 2000)
from Lieferant L
where exists
( select *
from liefert lief
where lief.Lnr = L.Lnr and lief.Wnr = 3 )
Schließlich kann man die Anfrage auch ganz einfach als (Semi-)Join formulieren:
select distinct L.Name
from Lieferant L, liefert lief
where L.Lnr = lief.Lnr and lief.Wnr =3
Am effizientesten auszuwerten sind i. Allg. die letzte und die erste Anfrage, da
man beide mit Hilfe eines Semijoins realisieren kann. Die Anfragen mit korrelierter Subanfrage werden dagegen von den meisten SQL-Systemen wesentlich
weniger effizient ausgewertet. Diese Möglichkeiten wurden auch eher als abschreckende Beispiele gebracht. Immerhin sieht man daran, dass die Verknüpfung von
Tabellen auch ohne Join möglich ist, wenn Subanfragen unterstützt werden. Man
muss also als Programmierer immer aufpassen, ob es im Falle von (korrelierten)
Subanfragen nicht auch einfachere – und effizientere Lösungen gibt.
Der in-Operator wird häufig verwendet, wenn man am Vergleich mit einer Vielzahl von Elementen interessiert ist:
select * from Ware
where Typ in (’CPU’,’RAM’,’GRAPHIKKARTE’);
anstelle von
select * from Ware
where Typ = ’CPU’ or
Typ = ’RAM’ or
Typ = ’GRAPHIKKARTE’;
Die obige Schreibweise ist eine Abkürzung für:
select * from Ware
where Typ in (values ’CPU’, ’RAM’, ’GRAPHIKKARTE’);
Mit dem Schlüsselwort values kann in SQL2 eine anonyme, d. h. namenlose
Tabelle temporär erzeugt werden:
values (1, ’Maier’, ’Königsbrunn’),
(2, ’Müller’, ’Augsburg’)
Allerdings wird dieser Mechanismus von vielen Datenbanken zurzeit nur im Zusammenhang mit dem insert-Befehl unterstützt. Die obige Schreibweise (Typ
in (’CPU’, ÜBÜBÜ )) wird dagegen von den meisten Datenbanken unterstützt.
Draft (2. März 2000)
52
Noch’n Beispiel
Welche Lieferanten liefern zumindest einige derjenigen Waren, die Lieferant 1
liefert (nur Lieferantennummern):
select distinct l.Lnr
from liefert l
where l.Wnr in
( select l.Wnr
from liefert l
where l.Lnr = 1)
Man beachte, dass l.Wnr außerhalb der Subanfrage eine andere Bedeutung hat
als innerhalb. Man könnte zur Verdeutlichung außerhalb auch überall l1 und innerhalb überall l2 schreiben.
Andererseits könnte man in diesem Fall – da es sich um eine nicht-korrelierte
Subanfrage handelt – auch auf alle fett geschriebenen Tupelbezeichnungen (Aliasnamen) völlig verzichten. Ich tendiere allerdings dazu, immer eindeutige Tupelbezeichner zu verwenden, da man diese – als menschlicher „Parser“ – besser, d. h.
fehlerfreier lesen kann.
Der Match-Operator
Wie bereits erwähnt wurde, bedeutet <Wert> match <Tabelle> dasselbe wie
<Wert> in <Tabelle>. Daneben gibt es noch den Operator match unique:
<Wert> match unique <Tabelle>.
Dieser Test liefert nur dann true, wenn die Tabelle genau ein Element besitzt –
und zwar <Wert>. Im Zusammenhang mit Nullwerten gibt es noch weitere Match-Varianten, die hier aber nicht diskutiert werden sollen.
Die All- und Some-Operatoren
Es gibt die Möglichkeit einen Wert mit allen (all) oder einigen Elementen – d. h.
mindestens einem Element (some, any) zu vergleichen.
Billiger als alle:
Preis <=all (select Preis from liefert where
ÜBÜCÜ )
Billiger als irgendeiner (nicht der teuerste):
Preis <some (select Preis from liefert where
ÜBÜCÜ )
Es gibt all und some (= any) für die Operatoren =, <, <=, >, >= und <>.
Wie bereits gesagt wurde, gilt in = =some und not in = <>all.
53
Draft (2. März 2000)
Achtung: In Umgangsenglisch kann any nicht nur irgendeiner/s, sondern auch
jeder bedeuten (Get those parts whose price is less than that of any blue part.)
Aus diesem Grund ist es besser immer some anstelle any zu verwenden.
✎
✎
" ÃÄ$Å%ÆÇÈÉÅÊ&ËÃÌp’aý—ÅþÉ|ÿBÿ
ÆÇÈÉÅÊËÃ̘ ý—ÅþɊ!Cÿ
Der Exists-Operator
Dieser Operator dient dazu, festzustellen, ob eine Tabelle leer ist oder nicht.
exists <Tabelle>
Verwendungsmöglichkeiten – insbesondere zur Realisierung des Allquantors –
wurden bereits ausführlich diskutiert.
Der Unique-Operator
Dieser Operator kann genutzt werden, um festzustellen, ob in einer Tabelle Duplikate vorkommen (false) oder nicht (true):
unique <Tabelle>
Achtung: unique funktioniert nur mit der SQL-Multimengensemantik, nicht
aber mit der Mengensemantik der relationalen Algebra (da Mengen niemals Duplikate enthalten).
Beispiel
Welche Artikel werden von mehreren Händlern zum billigsten Preis angeboten?
select W.Wnr, W.Name
from Ware W
where not unique
( select W.Wnr // oder l1.Wnr oder ’Wert ist egal’
from liefert l1
where l1.Wnr = W.Wnr and
l1.Preis <=all ( select l2.Preis
from liefert l2
where l2.Wnr = W.Wnr
)
)
Andere Lösung (mit Gruppierung und Aggregation; siehe Abschnitt 3.4)
select l1.Wnr
Draft (2. März 2000)
54
from liefert l1
where l1.Preis <=all ( select l2.Preis
from liefert l2
where l2.Wnr = l1.Wnr
)
group by Wnr
having count(l1.Lnr) > 1
Man beachte, dass man dieselbe Anfrage auch mit reiner Mengensemantik beantworten kann, d. h. ohne den Operator unique und ohne Aggregation. Allerdings
ist dies deutlich aufwendiger, da man dazu zwei exists-Operatoren benötigt: Es
gibt einen Lieferanten L1, der zum billigsten Preis liefert, und es gibt einen zweiten Lieferanten L2 × – L1, der ebenfalls zum billigsten Preis liefert (SQL-Query
selbst formulieren!).
" ÃÄ$Å%ÆÇÈÉÅÊ&ËÃ̘ ý—ÅþɊBÿ
ÆÇÈÉÅÊËÃ̉üûdý—ÅbþɟÿBÿ
✎
✎
3.4 Aggregation und Gruppierung
SQL bietet neben den Standard-RelAlg-Operatoren auch noch Aggregation und
Gruppierung. Diese sind für die Praxis sehr wichtig (bedeuten aber für die zugrundeliegende Theorie deutlich mehr Aufwand).
3.4.1 Aggregation ohne Gruppierung
Wie lautet der Durchschnittspreis des Artikels Nr. 3?
select avg(Preis)
from liefert
where Wnr = 3
Wieviele verschiedene Artikel werden derzeit angeboten?
select count(*)
from Ware
oder genauer (wenn lieferbare Waren gemeint sind):
select count(*)
from (select distinct Wnr from liefert)
55
Draft (2. März 2000)
oder kürzer
select count(distinct Wnr)
from liefert
In allen diesen Fällen wird eine Menge von Tupeln auf einen einzigen Wert abgebildet. Diesen Vorgang nennt man Aggregation.
SQL unterstützt folgenden Aggregationsfunktionen
count: Zähle Elemente
sum:
Bilde (numerische) Summe
avg:
Bilde (numerischen) Durchschnitt
min:
finde Minimum
max:
finde Maximum
Bei allen Aggregationsfunktionen kann man bestimmen, ob Duplikate berücksichtigt werden sollen (all = Defaultwert) oder nicht (distinct). Für die Minimum- und Maximum-Berechnung macht dies allerdings keinen Unterschied.
Aggregatfunktionen können nicht geschachtelt werden:
select avg(sum(x)) ÜBÜBÜ ist Nonsense.
3.4.2 Aggregation mit Gruppierung
Tabellen können vor der Aggregation in Gruppen eingeteilt werden. Die Aggregation wird dann für jede Gruppe separat durchgeführt. Im Gegensatz zur Aggregation ohne Gruppierung liefert die Aggregation mit Gruppierung i. Allg. mehr als
ein Element als Ergebnis (und zwar für jede Gruppe eines).
Beispiel
liefert
Lnr Wnr
1
1
2
1
3
1
1
2
3
2
Preis
50
100
150
50
100
Wie lautet der Durchschnittspreis der einzelnen Waren?
Hier müssen die Daten also nach den Lieferanten gruppiert werden:
Draft (2. März 2000)
56
select
Lnr, avg(Preis)
from
liefert
group by Wnr;
Ergebnis
Wnr avg(Preis)
1
100
2
75
Man beachte: Wenn in der Projektionsliste Aggregatsfunktionen aufgerufen werden, dürfen Gruppierungsattribute aus der group-by-Klausel nur ohne Aggregatsfunktion in der Projektliste stehen. Alle anderen Attribute dürfen nur mit Aggregatsfunktion in die Projektionsliste geschrieben werden.
" ÃÄ$Å%ÆÇÈÉÅÊ&ËÃ̉ ý—ÅþÉ|ÿBÿ
ÆÇÈÉÅÊËÃÌp’aý—ÅþɊ!Cÿ
✎
✎
Man kann auch Bedingungen für ganze Gruppen angeben: Alle Gruppen mit mehr
als drei Elementen, mit einem Durchschnittspreis ; ÜBÜBÜ etc. Dazu gibt es die Having-Klausel, deren Attribute (genauso wie in der Projektionsliste) wie folgt aussehen müssen: group-by-Attribute werden ohne Aggregationsfunktion aufgerufen, alle anderen Attribute mit Aggregationsfunktion.
Wie lautet der Durchschnittspreis für jeden Artikel billiger als 1000 DM, für den
es mindestens drei verschiedene Preise (< 1000 DM) gibt?
select
from
where
group by
having
Wnr, avg(Preis) as Durchschnittspreis
liefert
Preis < 1000 // and Wnr < 100 erlaubt
Wnr
count (distinct Preis) >= 3;
// and Wnr < 100 auch hier erlaubt
Man beachte, dass die Bedingung Preis < 1000 nur in der Where-Klausel
stehen darf, da sie gruppenunspezifisch ist. Die Bedingung count(distinct
Preis) >= 3 darf dagegen nur in der Having-Klausel stehen, da sie eine
gruppenspezifische Aggregatsfunktion beinhaltet. Bedingungen zu Gruppierungsattributen wie Wnr < 100 dürfen in beide Bedingungsklauseln eingefügt werden. Hier entscheidet der Geschmack.
3.5 Sortierung
SQL realisiert nicht die Mengensemantik der Relationalen Algebra, sondern eine Multimengensemantik. Das heißt, Duplikate werden nicht automatisch ent57
Draft (2. März 2000)
fernt. Dies ist z. B. für Aggregation notwendig. Allerdings realisiert SQL keine
Listensemantik. Das heißt, die Reihenfolge der Ergebnistupel einer Anfrage ist
nicht festgelegt und kann sich bei denselben Daten und denselben Anfragen von
Datenbanksystem zu Datenbanksystem unterscheiden. Wenn es auf die Reihenfolge der Ergebnistupel ankommt, kann man daher ans Ende des äußersten Select-Statements immer eine Order-by-Klausel anhängen:
Beispiel
Sortiere die Lieferanten nach ihrer Adresse (= Wohnort) und innerhalb der Wohnorte alphabetisch:
select
*
from
Lieferant
order by Adresse, Name
Es können beliebig viele Attribute der Ergebnis-Projektionsliste in der Order-by-Klausel angegeben werden.
Jedes Attribut kann dabei aufsteigend (ASC, default) oder absteigend (DESC) sortiert werden:
select * from Lieferant order by Name desc
3.5.1 Zusammenfassung
Eine Select-Anfrage sieht wie folgt aus (die Nummerierung bezeichnet dabei die
zeitliche Abfolge der Abarbeitung):
5
1
2
3
4
6
7
✎
select
<Projektionsliste>
from
<Relationen + Joins>
[where
<Bedingung>]
[group by <Gruppierungsattribute>]
[having
<Gruppenbedingung>]
[union|except|intersect
select
[order by <Sortierungsattribute>]
ÜCÜBÜ ]
ÆÇÈÉÅÊËÃÌp’aý—ÅþɊ!Cÿ
3.6 Modifikation des Datenbestandes
Die relationale Algebra sagt nichts darüber aus, wie man einen Datenbestand erzeugt und pflegt. Sie geht einfach davon aus, dass eine Menge von Relationen
Draft (2. März 2000)
58
bekannt ist. SQL bietet dagegen nicht nur die Möglichkeit, einen Datenbestand
per Anfragesprache zu untersuchen (select), sondern auch ihn zu manipulieren
(insert, delete, update).
ÆÇÈÉÅÊËÃ̘ ý—ÅþÉ|ÿ™Cÿ
✎
3.6.1 Insert
Es gibt zwei Möglichkeiten, Daten in eine Datenbank via Insert einzufügen.
1. Direkt
insert into Lieferant(Lnr,Name)
values (4, ’Huber’)
Anmerkung: Nicht aufgeführte Attribute werden mit einem Defaultwert (siehe unten) oder Null initialisiert.
insert into Lieferant
values ( (select max(Lnr)+1 from Lieferant),
’Huber’, ’München’)
insert into Lieferant // Nicht-SQL2
table ( (4, ’Huber’, ’München’),
(5, ’Meyr’, ’Rosenheim’) )
2. per Select- Statement
insert into Lieferant // SQL2
select * from
(values (4,’Huber’,’München’),
(5,’Meyer’,’Rosenheim’)
)
insert into Lieferant
select * from LieferantMuenchen
Achtung: Neben dem Insert-Befehl bieten die meisten DBs noch die Möglichkeit, externe Daten (z. B. in einem festen ASCII/ISO-Latin-Format) direkt in
die Datenbank einzulesen (spool in) oder direkt in eine externe Datei auszugeben
(spool out). Der Spoolvorgang ist allerdings nicht standardisiert.
3.6.2 Delete
Daten können aus einer Datenbank auch wieder gelöscht werden:
59
Draft (2. März 2000)
Alle Maiers und Mairs und Maierhubers sollen gelöscht werden:
delete
from Lieferant
where Name like ’Mai%r’
Alle Tupel sollen gelöscht werden:
delete from Lieferant
Um die ganze Tabelle zu entfernen, muss man allerdings Folgendes schreiben:
drop table Lieferant
(Gegenteil von create table)
3.6.3 Update
Bestehende Datensätze können modifiziert werden.
Alle Maiers erhöhen ihre Preise um 10 % und ihre Lieferfristen um einen Tag:
update liefert
set Preis = Preis*1.10, Lieferzeit = Lieferzeit+1
where Lnr in
(select Lnr from Lieferant
where Name = ’Maier’)
Achtung: Ein Update kann auch auf Schlüsselattributen erfolgen, meist allerdings
unter Performanzeinbußen.
3.6.4 Allgemeine Anmerkungen
Bei Update- und Insert-Befehlen können die zwei Sonderwerte Null und
Default angegeben werden. Default bezeichnet dabei den Defaultwert des
aktuellen Datentypes.
Der Programmierer kann den Defaultwert einer Tabellenspalte bei der Definition
der entsprechenden Tabelle
create table Lieferant
(Name varchar(20) default ’???’,
ÜBÜBÜ )
oder mit Hilfe von Domänendefinition
create domain namestring as varchar(20) default ’???’
Draft (2. März 2000)
60
create table Lieferant (Name namestring,
ÜBÜCÜ )
festlegen.
Modifikation am Datenbestand sind nur unter bestimmten Bedingungen erlaubt:
1. Der Benutzer muss die entsprechenden Rechte besitzen.
2. Durch die Modifikation werden keine Integritätsbedingungen verletzt.
3. Die zugehörige Transaktion wird durch commit oder Autocommit beendet
(und nicht etwa durch rollback verworfen).
4. Der Commit wird erfolgreich beendet. Insbesondere heißt das, dass keine der
Integritätsbedingungen, deren Überprüfung bis zum Commitzeitpunkt verzögert wurden, auf einen Fehler läuft.
5. Die Datenbank wird nicht durch einen Recoveryvorgang im Katastrophenfall
auf einen älteren Zustand zurückgesetzt.
Modifikationsoperationen erfolgen zweistufig:
Erst wird alles berechnet, was geändert werden soll, dann werden die Änderungen
durchgeführt. Wäre dem nicht so, so wären die Ergebnisse folgender Operationen
nicht vorhersagbar, da sich der Durchschnittspreis mit jedem Tupelupdate verändern würde:
delete from liefert
where Preis > (select avg(Preis) from liefert)
update liefert
set Preis = 0.9*Preis
where Preis > 2*(select avg(Preis) from liefert)
ÆÇÈÉÅÊËÃ̘üûdý—ÅbþɟÿBÿ
✎
3.7 Views
ÆÇÈÉÅÊËÃ̚
✎
In SQL ist es möglich, sogenannte views (virtuelle oder berechnete Relationen)
zu definieren.
create view Liefer (Name, Adresse, Wnr, Preis, Dauer) as
select L.Name, L.Adresse,
61
Draft (2. März 2000)
lief.Wnr, lief.Preis, lief.Lieferzeit
from Lieferant L, liefert lief
where L.Lnr = lief.Lnr
Eine view kann in Select-Anweisungen wie eine normale Relation (stored table) eingesetzt werden.
select avg(Preis) from Liefer
where Name=’Maier’
Insbesondere kann eine View auch zur Definition anderer Views eingesetzt werden. Falls allerdings eine View wieder gelöscht wird (z. B. drop view Liefer) sind alle anderen Views und alle Integritätsbedingungen, die sich auf diese
View abstützen, ungültig. Man kann dies verhindern, indem man das Löschen
entweder abbricht, wenn noch Abhängigkeiten bestehen (drop view <name>
restrict), oder alle abhängigen Views und Integritätsbedingungen automatisch mitlöscht (drop view <name> cascade).
Ein nachträgliches Ändern einer Views (alter view) ist im Gegensatz zu Tabellen (alter table) in SQL2 nicht möglich. Views können in SQL2 gar nicht
und in SQL3 nur eingeschränkt rekursiv definiert werden. Das ist sehr schade, da
damit SQL berechnungsvollständig (turingmächtig) wäre. Zum Beispiel könnte
mit rekursiven Views das Pfadproblem (Welche Pfade führen – evtl. über mehrere
Zwischenknoten – von A nach B?) gelöst werden. Das Pfadproblem tritt in der
Praxis sehr häufig auf (Zugverbindungen, Flugverbindungen, Internetverbindungen, Vorfahren/Nachfahren/Verwandschafts-Beziehungen etc.).
Beispiel Vorfahren
Es sei Eltern(Kind,Elter) eine Relation, in der zu jeder Person Kind ein
Elternteil Elter angegeben ist.
Kind
Elter
Sibylle
Sibylle
Marianne
Marianne
Franziska
.
.
.
Wolfgang
Marianne
Jakob
Franziska
Theresia
create view Vorfahren (Person, Vorfahre) as
(select * from Eltern) // Abbruchbedingung
union
Draft (2. März 2000)
62
(select V.Person, E.Elter // Rekursion
from Vorfahren V, Eltern E
where V.Elter = E.Kind
)
Diese View beschreibt folgende Vorfahren-Tabelle:
Kind
Sibylle
Sibylle
Marianne
Marianne
Franziska
Elter
Wolfgang
Marianne
Jakob
Franziska
Theresia
Sibylle
Sibylle
Marianne
Jakob
Franziska
Theresia
2. Generation
Sibylle
Theresia
3. Generation
1. Generation
Verfahren, um rekursive Views effizient zu berechnen sind heute gut erforscht,
allerdings auf dem Gebiet der sogenannten deduktiven Systeme. Deduktive Sprachen und Datenbanksysteme wurden in den letzten 15 Jahren erforscht, waren
aber nicht sehr erfolgreich – und so werden die dabei gewonnenen Erkenntnisse
bislang nicht in anderen Gebieten (wie z. B. RDBS) eingesetzt.
Das ist insofern verwunderlich, da zwischen RDBS und deduktiven DBS (DDBS)
– abgesehen von syntaktischen Unterschieden – nur ein wesentlicher Unterschied
besteht: DDBS erlauben rekursive Views, RDBS dagegen nicht.
Ein Problem der rekursiven Views ist, dass man die Ergebnisgröße eines Ergebh
nisses nur sehr schwer abschätzen kann ( automatische Optimierung ist sehr
schwer).
Beispiel
Wenn man u Netzknoten (Bahnhöfe, Flughäfen, Router etc.) hat und man berechnen will, von welchem Knoten zu welchem Knoten Verbindungen existieren,
f
enthält das Ergebnis zwischen u und u Tupel:
u
Jeder Knoten ist nur mit sich selbst verbunden.
u f Jeder Knoten ist mit jedem verbunden.
Leider lässt sich anhand statistischer Daten vor der eigentlichen Berechnung keine
genauere Abschätzung durchführen.
63
Draft (2. März 2000)
Die Tabellen
Start
1
2
3
Ziel
1
2
3
4
.
.
.
4
u
u
Start
1
2
3
.
.
.
Ziel
2
3
4
uœ›
u
u
1
sind statistisch vollkommen gleichwertig (gleichviele Tupel, jeder Wert kommt in
jeder Spalte gleichoft vor). Allerdings enthält die transitive Hülle, d. h. die Tabelle
f
aller möglichen Verbindungen im ersten Fall nur u Tupel im zweiten Fall u .
Fazit: rekursive Views bereiten bei der Abschätzung von Kosten den Optimierern
wesentlich mehr Probleme als nicht-rekursive Views.
3.7.1 Das View-Update-Problem
Views wurden nicht erfunden, um rekursive Definitionen zu ermöglichen oder
eine Verwandschaft zu den deduktiven Systemen herzustellen, sondern um bestimmten Benutzergruppen nur eine eingeschränkte Sicht (view!) auf die Datenbank zu erlauben. So könnte z. B. für die Inventarabteilung eine View erzeugt
werden, die es den Mitarbeitern dieser Abteilung ermöglicht, Name, Zimmernr
und Telefonnr aller Mitarbeiter, nicht aber deren Gehalt und Familienstand zu erfragen. Dazu müssen für die Mitarbeiter der Inventarabteilung eine oder mehrere
Datenbankbenutzergruppen erzeugt werden, die lediglich das Recht haben, diese
View zu lesen, nicht aber die Orginaltabelle.
Ein nächster Schritt wäre, diesen Mitarbeitern auch gewisse Updates zu erlauben.
In diesem Fall müssten die Befehle insert, delete und update auch für
Views ermöglicht werden. Doch das ist nur sehr eingeschränkt möglich. Wenn
z. B. eine View mit Hilfe zweier Relationen aufgebaut wurde, ist das Einfügen
eines Tupels in die View in SQL2 nicht erlaubt, da i. Allg. nicht feststeht, welche
ein(?) oder zwei(?) Tupel in die zugehörigen Relationen eingefügt werden sollen.
In SQL2 sind Viewupdates nur unter ganz bestimmten Voraussetzungen erlaubt
(updatable views):
1. Die View basiert auf genau einer Relation oder einer updatable view (kein
Join, Union, Intersect, Except).
2. Select Distinct wurde nicht verwendet.
3. Es gibt deine Group-by- oder Having-Klausel.
Draft (2. März 2000)
64
4. Es sind nicht alle Where-Klauseln erlaubt.
5. Jede Spalte der Select-Klausel ist ein Aliasname für eine Tabellenspalte
(keine Arithmetik etc.).
6. Alle Spalten, für die keine Defaultwerte existieren (wie z. B. der Primärschlüssel), sind über die View zugänglich.
Â"ÃÄ$Å%ÆÇÈÉÅÊ&ËÃ̚
✎
65
Draft (2. März 2000)
Draft (2. März 2000)
66
Kapitel 4
Oracle
ÆÇÈÉÅÊËÃÌ?úüûdýBÅþÉwBÿ
✎
4.1 SQLPlus
rem:
Zeilenkommentar
/* */:
Blockkommentar
describe <table>:
Relationenschema der Tabelle <table>
spool <file>:
Ausgabe in Datei <file> umlenken
spool off:
Ausgabe auf Bildschirm
save <Datei>:
SQL-Code sichern
edit <Datei>:
Editiere Datei mit Standardeditor
host emacs <Datei>: Editiere Datei mit anderem Editor
start <Datei>:
Führe Inhalt der Datei aus
show feedback:
Zeige Inhalt einer SQLPlus-Variable
set feedback off/set feedback 10:
Setze Inhalt einer SQLPlus-Variablen
typische Variablen
feedback:
gibt Anzahl Zeilen aus, wenn das Ergebnis mehr als
feedback Zeilen hat
numwidth:
Anzahl Zeichen zum Darstellen von Nummern
linesize:
Länge einer Zeile in Zeichen
pagesize:
Anzahl Zeilen einer Seite
newpage:
Anzahl Leerzeilen zwischen zwei Seiten
67
Draft (2. März 2000)
pause on/off/<text>: Aufforderung Enter zu drücken, um nächste Seite zu
sehen
Die Datei login.sql im aktuellen Verzeichnis kann SQLPlus-Befehle enthalten, die
bei jedem Start von SQLPlus automatisch ausgeführt werden.
prompt login.sql geladen!
set feedback 6
set sqlprompt ’SQL>’
set numwidth 5
set pagesize 70
set linesize 132
define _editor = "vi"
4.2 Date
Nullstellige Funktion SysDate:
select SysDate from dual;
SysDate
01-Nov-98
Die Tabelle dual hat eine Spalte und eine Zeile (Dummytabelle).1
Außerdem gibt es die Tabelle holiday mit amerikanischen Feiertagen.
Datumsfunktionen
– ADD_MONTHS(<Datum>,<Anzahl Monate>)
– GREATEST(<Datum1>,<Datum2>, ÜBÜCÜ )
– LEAST(<Datum1>,<Datum2>, ÜBÜCÜ )
– LAST_DAY (<Datum>)
letzter Tag des Monats
– NEXT_DAY(<Datum>,<Wochentag>)
nächster <Wochentag> nach <Datum>
– MONTHS_BETWEEN(<Datum1>,<Datum2>)
– TO_CHAR(<Datum>,<Format>)
Datum in String umwandeln
1
Eine weitere Anwendung von dual: select 317*712+5 from dual;
Draft (2. März 2000)
68
– TO_DATE(<String>,<Format>)
String in Datum umwandeln
– ROUND<Datum> runde taggenau
– TRUNC<Datum>
schneide Stunden, Minuten, Sekunden ab Mitternacht ab
select TO_DATE(’02-APR-99’) - ROUND(SYSDATE) from dual;
select TRUNC(SYSDATE) + 1 from dual; morgen
select TRUNC(SYSDATE) + 0.5 from dual; heute Mittag
Formatanweisungen
Die Konvertierung von Zeichenketten in das Datumsformat und umgekehrt erfolgt
über Formatstrings. Ein Formatstring kann Schlüsselwörter, Sonderzeichen und
uninterpretierte Zeichenketten (" ÜCÜBÜ ") enthalten.
Schlüsselwörter von Formatstrings:
MM:
Monat als Nummer
RM:
Monat als römische Nummer
MON:
3-buchstabiger Monatsname (AUG)
MONTH:
Monatsname
DDD:
Tage seit Beginn des Jahres
DD:
Tage seit Beginn des Monats
D:
Tage seit Beginn der Woche
DY:
3-buchstabiger Wochentag
DAY:
Wochentag
YYYY:
Jahr (4 Ziffern)
YY:
Jahr (2 Ziffern)
IYYY:
ISO-Jahr (4 Ziffern)
IY:
ISO-Jahr (2 Ziffern)
Q:
Quartal
WW:
Kalenderwoche
IW:
ISO-Kalenderwoche
W:
n-te Woche im Monat
69
Draft (2. März 2000)
HH,HH12: Stunde 1-12
✎
HH24:
Stunde 1-24
MI:
Minute
SS:
Sekunde
SSSSS:
Anzahl Sekunden seit Mitternacht
Â"ÃÄ$Å%ÆÇÈÉÅÊ&ËÃÌEúüûdýBÅþÉwBÿ
Draft (2. März 2000)
70
Kapitel 5
Datenbankensysteme und
Multimedia
SQL2 sieht bislang keine Unterstützung von Multimedia vor. Das wird sich
allerdings mit SQL3 ändern. Doch praxistaugliche Implementierungen des
SQL3-Standards wird es in den nächsten fünf bis zehn Jahren aller Voraussicht
noch nicht geben.
Hier soll nun untersucht werden, inwieweit bereits heutige Datenbanksysteme
in Multimediaanwendungen, insbesondere in Internet-Anwendungen, eingesetzt
werden können.
5.1 Anforderungen an ein Multimedia-Datenbanksystem
Welche Eigenschaften sollte ein gutes MMDBS erfüllen?
1. Es sollte ein vollwertiges Datenbanksystem sein:
– Persistenz (d. h., dauerhafte Speicherung der Daten)
– Transaktionen (Robustheit im Fehlerfall)
– Recovery (Robustheit im Katastrophenfall)
– Mehrbenutzerfähigkeit
– Integritätssicherung (Konsistenz)
– Performanz
– Ad-hoc-Anfragen
– etc.
2. Es sollte Multimedia-Objekte (Daten + Methoden) unterstützen: Text (insbesondere HTML/XML), Bild, Audio, Video, komplexe multi-mediale Objekte
h
( Interaktion, Synchronisation), Hyperlinks
3. Es sollte – für MM-Objekte – Informations-Retrieval-Fähigkeiten bieten
– Attributsuche (einfach, da DBS dies bereits bietet)
71
Draft (2. März 2000)
– Inhaltssuche (i. Allg. sehr schwierig), insbesondere Volltextsuche (nicht
so schwierig)
– navigierende Suche / Linkverfolgung (nicht so schwierig, wird aber derzeit nicht standardmäßig unterstützt)
Vorteile von MMDBS
1. saubere Verwaltung großer Mengen an Multimediadaten (z. B. erzeugen Abbrüche von langen Kopiertransaktionen keine Dateileichen)
2. Schneller Zugriff auf einzelne Objekte
(Gegenbeispiel: Unix-Directory mit 10 000 Objekten)
3. optimierte Ablage von MM-Objekten. Verwaltung von CD-ROM-Archiven
(Jukeboxes), Bandarchieven, Plattenfarmen etc.
4. Datenbankeigenschaften: Mehrbenutzerbetrieb, Datensicherheit, Konsistenz
(z. B. referenzielle Integrität)1 etc.
5. effizientes Information Retrieval
6. Und anderes mehr
5.2 Relationale Datenbanksysteme und Multimedia
SQL2 bietet – bis auf den wenig performante LIKE-Selektor – keine MM-Unterstützung. Allerdings sind die Datenbankhersteller in diesem Punkt schon weiter:
– Die meisten Datenbanken können BLOBs (Binary Large Objects) verwalten.
– Volltextsuche wird von vielen Datenbanken unterstützt.
– Oracle unterstützt Quicktime
– Datenbanken auf CD-ROMs und CD-ROM-Jukeboxes werden unterstützt
(z. B. TransBase).
– Es ist möglich WWW-Seiten mit Datenbankunterstützung zu erstellen (z. B.
PHP und JDBC).
– Es gibt spezielle WWW-Datenbankserver (z. B. von Oracle).
Leider sind diese Techniken und Spracherweiterungen derzeit meist proprietärer
Natur. Das heißt, jeder Hersteller kocht sein eigenes Süppchen. Es gibt allerdings
1
Die referenzielle Integrität ist eine der wesentlichsten Schwachstellen der WWW: URLs zeigen
häufig ins Nirwana.
Draft (2. März 2000)
72
Bestrebungen auch in diesen Bereichen Standards – wie z. B. SQL3 – zu etablieren.
5.2.1 BLOBs
Normale SQL-Datentypen wie varchar oder binchar sind längenbeschränkt
(z. B. 4 KByte). Um große (binäre) Datensätze in Datenbanksystemen zu speichern wurden deshalb die sogenannten BLOBs (Binary Large Objects) eingeführt.
Allerdings dürfen auch BLOBs nicht beliebig groß sein. So darf ein BLOB in
TransBase nicht größer als 2 GB (-1 % Overhead) und in Oracle 8 nicht größer
als 4 GB (glaube ich) sein. In TransBase ist die Größe einer Tabelle außerdem
auf 4 Terrabyte (-1,5 % Overhead) beschränkt (Oracle: weiß ich noch nicht). Dies
reicht für die meisten Anwendungen aus, kann aber zu Engpässen im Videobereich führen. Oracle hat angekündigt, in Zukunft auch BLOBs beliebiger Größe
zu unterstützen.
Beispiel für BLOBs (TransBase)
create table employee
(
id
integer
name
char(*), // varchar(4096)
picture
blob,
signature
blob,
primary key(id)
)
Datenbankoperationen auf BLOBs:
– Einfügen, Löschen, Ersetzen
– Test auf null (where picture is not null)
– Bestimmung der Größe in Bytes (size of picture)
– Selektion des ganzen Blobs oder eines Teilbereichs (picture subrange(1,100),
signature subrange(100, size of signature))
Gleichheitstest werden nicht unterstützt, alle BLOBs gelten als verschieden (wichtig für distinct und Gruppierung). Primär- und Sekundär-Indexe können nicht
angelegt werden. BLOBs können nicht direkt über die Ad-hoc-Query-Interfaces
(UFI, XUFI, TBI) eingelesen und ausgegeben werden. Die Ein- und Ausgabe erfolgt entweder mit Hilfe des proprietären TransBase-Spool-Mechanismuses oder
über ESQL (Emdedded SQL = in 3GL-Sprache eingebettet SQL-Code).
73
Draft (2. März 2000)
In ESQL fängt jeder SQL-Befehl mit EXEC SQL an und hört mit ; auf. C- (oder
C++- oder COBOL- oder sonstige) Variablen, auf die in einem SQL-Statement
zugegriffen wird, müssen zunächst in einer DECLARE SECTION definiert werden. In SQL-Statements kann auf derartige Variablen zugegriffen werden, indem
man sie mit einem Doppelpunkt versieht.
Datei beispiel.c mit ESQL-Befehlen
// Definition von Variablen
EXEC SQL BEGIN DECLARE SECTION;
blobdesc myblob;
EXEC SQL END DECLARE SECTION;
myblob.mode = FILENAME;
myblob.loc.filename = "MeinBild.gif";
EXEC SQL
INSERT INTO graphic
VALUES (’Bild 1’, :myblob);
EXEC SQL
UPDATE graphic SET image = :myblob
WHERE name = ’Bild 1’;
5.2.2 CD-ROM-Datenbanken
Multimediadaten benötigen vor allem eines: Platz. So ist es nicht verwunderlich,
dass billiger Speicherplatz ein begehrtes Datenbankmedium ist.
Den billigsten Speicherplatz stellt heute immer noch das Magnetband dar. Allerdings sind die Zugriffszeiten – wegen der linearen Suche – meist indiskutabel
langsam. So eignen sich Bänder nur für wenige Anwendungsgebiete wie z. B. Video on Demand (ein Film = ein Blob pro Band). Das jeweils gesuchte Band kann
h Datenbanken im Terrabytebereich.
dabei von Robotern eingelegt werden
Ein anderes sehr billiges Speichermedium ist die CD-ROM. Auch hier können
viele CD-Roms von einer sogenannten Jukebox verwaltet werden (Platz für mehrere 100 CDs sowie einen oder mehrere CD-Leser). Jede CD-ROM ist dann in
einem von drei Zuständen:
online:
CD-ROM ist im Lesegerät
nearline: CD-ROM ist in der Jukebox
Draft (2. März 2000)
74
offline:
CD-ROM ist außerhalb de Jukebox und wird bei Bedarf vom Operator
eingelegt
Der Zugriff auf Online-CDs dauert einige Millisekunden, der Zugriff auf Nearline-CDs einige Sekunden und der Zugriffauf Offline-CDs mehrere Minuten
(wenn’s gut geht).
Um teure Nearline-Zugriffe zu vermeiden, sollten Daten, die häufig gemeinsam
benötigt werden, nach Möglichkeit auf einer CD-ROM untergebrachte werden.
TransBase bietet beispielsweise die Möglichkeit CD-ROM-Datenbanken zu erstellen:
1. Entwicklung einer Datenbank wie gewohnt.
2. Erzeugung der späteren CD-ROM-Datenbank zunächst auf Festplatte (Testphase).
3. Brennen der CD-ROM.
4. Einrichten der CD-ROM-Datenbank
5. Benutzen der Datenbank mit zweistufigem Cache: Hauptspeicher und Festplatte. Es ist auch möglich, Daten auf der CD-ROM zu „überschreiben“. Dazu werden die neueren Tupel auf der Festplatte abgelegt und die alten Tupel
verschattet (auf der Festplatte als ungültig markiert).
5.2.3 RAID (Plattenfarmen)
Idee: mehrere (viele) Platten zu einer logische Platte zusammenschalten
Vorteile:
– Hohe Bandbreite (z. B. für Video on Demand)
– Fehlertoleranz durch redundante Speicherung
– billig, da billige Platten eingesetzt werden können
RAID = Redundant Arrays of Inexpensive Discs
RAID level 0: data stripping
h
Die logischen Sektoren werden über u Platten verteilt
u aufeinanderfolgende
Sektoren können gleichzeitig gelesen oder geschrieben werden (sofern der Datenbus breitbandig genug ist).
75
Draft (2. März 2000)
Platten
1
2
3
4
5
1
1
2
3
4
5
2
6
7
8
9
10
3
.
.
.
11
.
..
12
.
..
13
.
..
14
.
..
15
.
..
Sektoren
Level 0
h
schneller Zugriff, keine Redundanz
RAID level 1: mirrored disks
Die Daten werden auf zwei Platten gleichzeitig abgelegt
h
Level 1 normaler Lese- + Schreibzugriff, hohe Redundanz
RAID Level 2-4: data stripping + parity disks
Für jeweils u Sektoren werden auf einer oder mehreren Extra-Platten Parity-Informationen zur Restauration von fehlerhaften Daten abgelegt.
Platten
1
2
3
4
5
P
1
1
2
3
4
5
P1
2
6
7
8
9
10
P2
3
11
12
13
14
15
P3
.
..
.
..
.
..
.
..
.
..
.
..
.
..
Sektoren
Level 2-4
h schneller Lesezugriff, langsamer Schreibzugriff (wegen
pot“-Parityplatte), Redundanz (nimmt ab mit wachsendem u ; u
mirroring)
Draft (2. März 2000)
76
„Hots× h
RAID Level 5: parity sections interleaved on disks
Um die Schreibgeschwindigkeit zu erhöhen, werden die Paritysektoren gleichmäßig über die Platten verteilt.
Platten
1
2
3
4
5
6
1
P1
1
2
3
4
5
2
6
P2
7
8
9
10
3
11
12
P3
13
14
15
.
..
.
..
.
..
.
..
.
..
.
..
.
..
Sektoren
level 5
h
schneller Schreib- + Lesezugriff (Schreibzugriff langsamer als Level 0), Redundanz
Anmerkung
Redundante Speicherung ist bei großen Plattenfarmen (mehrere 1000 Platten) sehr
wichtig, da die Mean Time Between Failures (MTBF) sehr gering ist:
h MTBF/10.000 Platten = 100 h = 5d
MTBF/Platte = 1.000.000 h
Das heißt, in großen Plattenfarmen (wie z. B. VoD-Servern wie dem Oracle Media
Server mit bis zu 25.000 Video-Streams gleichzeitig) müssen alle Platten regelmäßig im laufenden Betrieb überprüft und gegebenenfalls ersetzt werden können.
5.3 Volltextindexe (Inhaltssuche)
TransBase unterstützt die Volltexttextsuche auf Attributen vom Typ char( u ),
char(*) (= varchar(4096)) und blob.
Für jedes Attribute, das zur Volltextsuche eingesetzt werden soll, muss zunächst
ein Volltextindex erzeugt werden.
create [positional] fulltext index <name> <options>
on <table> (<attribute>)
77
Draft (2. März 2000)
– Positionelle Volltextindexe, d. h., Volltextindexe, die zu jedem Wort auch
noch die Wortposition abspeichern, sind umfangreicher als einfache Volltextindexe, ermöglichen aber Phrasensuche (siehe unten).
– Die Indexerstellung kann durch die Angabe diverser Optionen gesteuert werden:

WORDLIST FROM <table w>
 Nur Wörter aus der Tabelle <table w> indizieren (Lexikon).
STOP WORDS FROM <table s>
Wörter aus Tabelle <table s> nicht indizieren (z. B. der, die, das, ein,
 einer ÜBÜBÜ ).
CHARMAP FROM <table c>
Buchstaben ersetzen (A, B, C ÜBÜBÜ durch a, b, c ÜCÜBÜ ; ä, ö, ü, ß durch ae,
oe, ue, ss etc.). Die Tabelle <table c> hat zwei Spalten: char(1) und
 char(*).
DELIMITERS NONALPHANUM
DELIMITERS FROM <table d>
Standardmäßig werden Wörter durch Whitespaces voneinander getrennt. Das heißt, Sonderzeichen zählen als Buchstaben. Man kann aber
auch alle Sonderzeichen (d. h. Zeichen, die keine Zahlen oder Buchstaben sind) als Worttrenner behandeln (DELIMITERS NONALPHANUM). Oder man kann eine eigene Tabelle mit Worttrennsymbolen definieren.
Beispiel
CREATE POSITIONAL FULLTEXT INDEX abstract
ON buch (abstract)
Für jeden Volltextindex <f_index> gibt es Pseudotabellen:
– FULLTEXT WORDLIST OF <f_index> (word, wno)
– FULLTEXT STOPWORDS OF <f_index> (word)
– FULLTEXT CHARMAP OF <f_index> (source, target)
– FULLTEXT DELIMITERS OF <f_index> (delimword)
Diese können wie normale Tabellen in Select-Statements verwendet werden.
Außerdem sind folgende Modifikationen erlaubt: INSERT für WORDLIST und
DELETE für STOPWORDS. Dies hat allerdings nur einen Einfluss auf zukünftige Volltextindex-Updates (durch Inserts in die Basistabelle), nicht aber auf den
aktuellen Index-Inhalt.
Draft (2. März 2000)
78
Wichtiger ist jedoch das Volltextindex selbst. In TransBase gibt es das Spezialprädikat CONTAINS zur (boolschen) Volltextsuche.
Beispiele
Wortsuche
select * from Buch
where abstract
contains (’database’)
Phrasensuche
select * from Buch
where abstract
contains (’database’ ’systems’)
Wildcardsuche
% und _ haben dieselbe Bedeutung wie im Prädikat LIKE.
Nur ist die Suche mit Mitten- und/oder Endtrunkierung (Wasch%, Wasch%en,
Wasch%en%) i. Allg. wesentlich effizienter als bei LIKE. Lediglich die Suche
mit Anfangstrunkierung (%Lappen) ist langsam (siehe aber unten).
select * from Buch
where abstract
contains (’data%’)
Wenn man nach einem %, \ oder _ sucht, muss man \%, \\ bzw. \_ schreiben.
Wortabstand
select * from Buch
where abstract
contains (’data%’ [0,3] ’bases’)
Hier wird ein Wort beginnend mit data, gefolgt von bis zu drei beliebigen Wörtern, gefolgt vom Wort bases gesucht (zum Beispiel data and knowledge
bases). Die Schreibweise contains (’ ÜBÜBÜ ’ [ u ] ’ ÜCÜBÜ ’) ist eine Abkürzung für contains (’ ÜBÜBÜ ’ [0, u ] ’ ÜBÜBÜ ’).
Volltextsuche mit Boolschen Operatoren
Einzelne Phrasen können mit AND, OR, NOT und Klammerung verknüpft werden.
select * from Buch
where abstract
79
Draft (2. März 2000)
contains (
’object%’ [1] ’data%’ ’systems’
OR ’distributed’ [1] ’systems’ )
Multivalue-Atome
Suche alle Abstracts, die irgendein Wort aus der Tabelle Wortliste enthalten.
select * from Buch
where abstract
contains (ANY (select * from Wortliste))
Nicht-primitive Contains-Atome
Das Contains-Prädikat darf auch Attributzugriffe und sogar Subqueries enthalten.
Welche Wörter aus der Liste Wortliste kommen in meinen Abstracts vor?
select W.Wort form Wortliste W
where exists
(select * from Buch
where abstract contains(W.Wort))
✎
žŸQaM MNPO$Å~N*ÉʈiÅþÊZ*þÅÉN*ËQaM`ÃÇYQaM9Ä*þÅ~[!¡fÃ\2NŠ¢o£fÇäb­É \2NfÆwþÊ\2N?Ì$ÅSO$ÈIN¥QaM\#e
Performanz
Die Volltextsuche ist i. Allg. sehr schnell (Ausnahme: Anfangstrunkierung). Das
Einfügen neuer Tupel in eine Tabelle mit Volltextindex kann schnell erfolgen. Allerdings wird für die Erzeugung eines ganzen Indexes viel Platz benötigt. Je mehr
temporärer Speicher zur Verfügung steht desto besser. Man kann den temporären
Speicherplatz bei der Erzeugung des Indexes angeben: SCRATCH 60 MB.
Das Löschen ist dagegen sehr langsam ( AÕ`u Ö , wobei u die Größe des Indexes ist).
Es ist besser, viele Tupel auf einmal zu löschen als einzeln hintereinander.
Tips und Tricks
Eine gute Volltextsuche sollte unabhängig von Groß- und Kleinschreibung und
spezieller Schreibung der Umlaute funktionieren. Das heißt, man sollte eine
charmap der folgenden Bauart anlegen:
source
A
B
C
¦$¦$¦
target
a
b
c
Draft (2. März 2000)
80
Ä
Ö
Ü
ä
ö
ü
ß
ae
oe
ue
ae
oe
ue
ss
Diese Charmap wird sowohl bei der Indexerstellung als auch bei der Auswertung
von Anfragen verwendet. Das heißt, z. B. die Anfrage ¦$¦!¦ contains (’Mädchen’) ist gleichwertig zur Anfrage ¦$¦$¦ contains (’maedchen’).
Manchmal ist es allerdings wichtig, noch wesentlich fehlertoleranter zu arbeiten. Folgendes Verfahren funktioniert immer: Es gebe eine Abbildung
§©¨ Wort ª Wort, die jedes Wort in ein anderes Wort transformiert (z. B.
§
charmap « ’Mädchen’ ¬Y­ ’maedchen’)
1. Bei der Erstellung des Volltextindexes wird jedes Wort mittels §
miert, bevor es gespeichert wird.
transfor-
2. Jedes Wort einer Anfrage wird ebenfalls mittels § transformiert.
Beispiel
Mehrere phonetisch ähnlich klingende Laute können durch einen Laut ersetzt und
stumme Laute entfernt werden.
source
’f’
’F’
’p’
’P’
’c’
’h’
’z’
.
.
.
target
’ph’
’ph’
’b’
’b’
’k’
”
’s’
In diesem Fall werden auch fehlerhafte Schreibwesen in einer Anfrage akzeptiert:
Haubtbanhof, Fotograph.
Allerdings werden auch mehr Fehltreffer gefunden. Die Frage nach Haus liefert
auch das Wörtchen aus (außer man läßt nur das klein geschriebene h entfallen).
Man kann noch viel weiter gehen: Buchstabenverdopplungen werden entfernt,
ie wird durch i ersetzt, ck durch k, tz durch z, dt durch t, etc. Leider wird
81
Draft (2. März 2000)
dies von TransBase nicht mehr unterstützt, da die Charmap-Source immer nur aus
einem Zeichen bestehen kann.
Man kann sich aber dennoch helfen, wenn man eine C- oder C++-Routine hat, die
diese Transformationen vornehmen kann.
1. Wende die Routine auf alle Texte an, die volltextindiziert werden sollen und
speichere die transformierten Texte (evtl. zusätzlich zu den Orginaltexten) in
einer Tabelle ab:
create table Text
Id
integer
Text
blob,
Transformtext blob
.
.
.
);
2. Erzeuge einen Volltextindex auf den transformierten Texten.
3. Jede Benutzerangabe wird mit Hilfe der C/C++-Routine (oder einer Javascript-Routine etc.) transformiert, bevor sie an die Datenbank wietergeleitet wird
(Dynamic ESQL).
4. Optional: Jedes Wort eines Treffertextes wird wiederum mit der obigen Routine transformiert (allerdings nur temporär). Jedes Wort, dessen transformierte
Form der transformierten Anfrage genügt, wird als Treffer markiert (z. B. in
HTML farbig hervorgehoben).
Beispiel
Text 1: Dies kann man lesen
Text 2: Diesen Kahn fährt ein Mann
Trafo 1: dis kan man lesen
Trafo 2: disen kan faert ein man
Die Suche erfolgt nun viel fehlertoleranter als bislang. Es werden aber auch viel
mehr falsche Dokumente gefunden. Zum Beispiel liefert die Suche nach „Mann“
und „Kahn“ auch Text 1.
Weitere Möglichkeiten: alle Vokale weglassen, Wörter durch phonetische Äquivalenzen ersetzen (dazu braucht man ein phonetisches Lexikon, z. B. klingen „bot“
und „Boot“ gleich, nicht aber „kann“ und „Kahn“) etc.
Neben den Worttransformationen gibt es auch noch weitere Techniken, um fehlertolerante Volltextsuche zu ermöglichen.
Draft (2. März 2000)
82
Eine bekannte Technik besteht darin, die Wörter Texte in Trigramme (oder allegemein n-Gramme) zu zerlegen:
Busbahnhof = ® bu, bus, usb, sba, bah, ahn, hno, nof, of ®
Anfragen werden ebenfalls in n-Gramme zerlegt. Diejenigen Texte, in denen die
meisten der gesuchten n-Gramme vorkommen werden als Treffer angezeigt.
Vorteile:
– Bcuhstabenverdreher (sic.) können auch noch zu einem Ergebnis führen (nur
ein paar n-Gramme sind falsch)
– Zusammen- und Getrenntschreibung wird erkannt („Bahnhof für Busse“, gemeinsame Trigramme: bah, ahn, hno, nof, of ® , bus)
Nachteile:
– kleine n-Gramme liefern viele Fehler (Jedes Treffer-n-Gramm kann in einem
anderen Wort vorkommen.)
– große n-Gramme sind nicht sehr fehlertolerant
Fazit: Je fehlertoleranter eine Volltextsuche ist, desto mehr Fehltreffer liefert eine
Suche.
Ein weiteres Problem, die effiziente Suche mit Anfangstrunkierung, kann man
relativ einfach lösen. In TransBase wird jedem Wort ein Identifikator zugeordnet:
Wort
faehrt
gehen
gehoben
geht
wolfgang
Id
1
2
5
4
3
Die eigentliche Suche erfolgt mit den entsprechenden Identifikatoren, das heißt,
jedes Wort einer Anfrage wird durch den zugehörigen Identifikator ersetzt.
Endtrunkierung kann sehr effizient abgearbeitet werden, wenn diese Liste alphabetisch geordnet ist, d. h., wenn Wort als Primärschlüssel gewählt wurde. Man
muss nur das erste Wort in der Wortliste suchen, das mit dem gesuchten Teilwort
beginnt und dann der Reihe nach alle nachfolgenden Wörter mit demselben Anfang ebenfalls in die Suche einbeziehen (geh% ª Wörter 2, 5, 4).
Bei der Anfangstrunkierung bleibt einem zunächst nichts weiter übrig, als die
ganze Wortliste zu durchsuchen (%t ª 1 ¯ 4).
Der Trick ist nun, die Liste zu erweitern, indem man jedes Wort noch einmal
rückwärts geschrieben und geeignet markiert mit demselben Identifikator wie das
Ursprungswort in die Liste einfügt.
83
Draft (2. März 2000)
Wort
@gnagflow
@neboheg
@neheg
@theg
@trheaf
faehrt
gehen
gehoben
geht
wolfgang
Id
3
5
2
4
1
1
2
5
4
3
Wenn man jetzt die Anfrage %t (natürlich automatisch) durch @t% ersetzt, bekommt man die gesuchte Wortindexliste (4, 1) ganz schnell. Die einzigen Anfragen, die jetzt noch Schwierigkeiten machen, sind Anfragen mit Anfang und
Endtrunkierung: %ab% etc. oder gar % (ganz übel)2.
Weitere Volltexttechniken
Thesauri
Ein Thesaurus ist ein Synonymwörterbuch, das in einer Datenbank abgelegt wurde. Insbesondere können fachspezifische Thesauri angelegt werden, die Fachwörtersynonymen aus mehreren Sprachen enthalten.
Mathematik:
Körper
field
(nicht etwa: body)
Verband
lattice
(nicht etwa: bandage)
Halbachse Ellipsenhalbachse semi axis
Bei der Thesaurussuche werden automatisch Synonyma berücksichtigt. Aber auch
Thesauri sind nicht gegen Fehltreffer gefeit. Wie soll ein Thesaurus entscheiden,
ob mit Körper der medizinische Körper body oder der mathematische Körper
field gemeint ist.
Stammbildung
Einige Volltextsysteme reduzieren Suchwörter und Volltextindexe auf Wortstämme, d. h. sie benutzen die Abbildung § Wortstamm ¨ Wort ª Wort.
geht, ging, gegangen, gehend ¦!¦$¦ ª gehen
Datenbank, Datenbanken ª Datenbank
Haus, Häuser, Hauses ª Haus
2
In OMNIS wird diese Anfrage als unsinnig herausgefiltert. Das heißt aber nicht, dass man OMNIS nicht doch lahm legen kann: %a% oder sogar %% werden abgearbeitet, führen aber zu riesigen Ergebnissen.
Draft (2. März 2000)
84
Die Wortstammbildung ist allerdings nicht trivial und vor allem sprachabhängig.
Zum Beispiel ist nicht klar, welchen Stamm das Wort „Essen“ hat: „Essen“ (Stadt
in Deutschland), „essen“ (Substantivierung) oder „Esse“ (Pluralbildung).
WAIS
WAIS (Wide-Area Information Systems, pronounced ways) ist ein Volltext-Indizien- und Retrievalsystem, allerdings kein Datenbanksystem (Warum?).
WAIS basiert auf dem ANSI-Standard Z39.50 „Information Retrieval Service und
Protocol“ aus dem Jahr 1988.
WAIS besteht aus zwei Hauptkomponenten:
– Eine indexing engine, die für ein Textarchiv (oft fälschlicherweise schon
Datenbank genannt) einen Volltextindex erzeugt.
– Eine query engine, um Ad-hoc-Volltextanfragen auszuwerten
Für zugängliche WAIS-Implementierungen sind beispielsweise:
– freeWAIS (heute ZDist)
– freeWAISsf
Die indexing engine von freeWAIS heißt waisindex.
Neuen Index anlegen:
waisindex -export -d <Name Indexdatei> -T TEXT *.txt
waisindex -export -d <Name Indexdatei> -T PS
*.ps
Index erweitern:
waisindex -a -d <Name Indexdatei> -T TEXT *.txt
WAIS-Anfragen können auf verschiedene Arten erfolgen:
mittels waisq, waissearch, Perlinterfaces zu diesen Programmen etc.
waissearch -d <Name Indexdatei> <Wort>+
Das Programm waissearch kann auch Anfragen an Remote-Datenbanken
schicken, wenn diese dem Z39.50-Protokoll genügen. Dazu muss man den Rechner, den Z39.50-Port (Default 210) sowie die Remote-Datenbank kennen.
Anmerkung
Es gibt weitere Volltext-Engines (die evtl. nicht dem Z39.50-Standard genügen):
Glimpse, Harvest etc.
85
Draft (2. März 2000)
Fazit
Das Ziel jeder Volltextmaschine ist es, Anfragen vollständig und korrekt zu beantworten. Das heißt:
recall ­
°
relevant objects returned|
°
relevant objects in DB| ±
precision ­
°
²
relevant objects returned|
°
°
all objects returned
±
(es gilt immer ³ 1)
²
(es gilt immer ³ 1)
Leider sinkt bei heutigen Systemen fast immer die precision mit wachsendem
recall. Da heißt, obwohl es viele Volltextsuchtechniken gibt, sind hochwertige
Antworten häufig noch die Ausnahme.
5.4 Hypermedia (navigierende Suche)
Ein Link hat die Aufgabe, mehrere Dokumente (d. h. Texte oder andere Multimedia-Objekte) oder Teildokumente in Beziehung zueinander zu setzen.
Man unterscheidet zwischen:
1. Richtung der Links
– unidirektionale Links, die in eine Richtung von Linkquelle zu Linkziel
verfolgt werden können (z. B. WWW)
– bidirektionale Links, die in beide Richtungen verfolgt werden können
2. Granularität der Links
– Node-to-Node-Links: Linkquelle und Linkziel sind vollständige Dokumente (in HTML vorgesehen, von den meisten Browsern aber nicht unterstützt)
Draft (2. März 2000)
86
– Span-to-Node-Links: Linkquelle ist ein Teildokument, Linkziel ein vollständiges Dokument (z. B. WWW)
– Node-to-Span-Links: Linkquelle ist ein vollständiges Dokument, Linkziel ein Teildokument (in der Praxis sehr selten)
– Span-to-Span-Links: Linkquelle und Linkziel sind Teildokumente (in
WWW eingeschränkt vorhanden; HTML-Links können auf Tags innerhalb eines Dokuments zeigen; angezeigt wird allerdings immer das gesamte Dokument via Scrollbar)
3. Kardinalität der Links
– 1:1-Links: klassisch, z. B. WWW
– 1:n-Links: von einer Quelle aus können mehrere Ziele erreicht werden
87
Draft (2. März 2000)
– n:1-Links: von mehreren Quellen aus kann ein Ziel erreicht werden
– m:n-Links: von mehreren Quellen aus können mehrere Ziele erreicht
werden (auch MSMD-Links genannt: Multi-Source-Multi-DestinationLinks)
4. Lokalität der Links
– Inter-Dokument-Link
Draft (2. März 2000)
88
– Intra-Dokument-Link
–
–
–
–
Inter-Domain-Links (Domain = Rechner, Lan etc.)
Intra-Domain-Links
absolute Links
relative Links
Man beachte, dass alle Kombinationen aller Linkarten möglich sind: bidirektionale Span-To-Node-m:n-Links etc. Bei 1:n- und m:n-Links sind sogar noch zusätzliche Span- und Nodevarianten denkbar. Allerdings machen nicht alle möglichen
Links einen Sinn (wie z. B. Intra-Node-to-Node-Links).
Links können außerdem benannt sein und beliebige andere Attribute enthalten,
wie z. B. ein Attribut Relevanz, das einen Wert zwischen unrelevant (=0) und
sehr relevant (1) annehmen kann. Links können außerdem zusätzliche Attribute
(wie z. B. Häufigkeit) und/oder Rollennamen an den jeweiligen Linkenden
enthalten.
Auto
0-1
Bestandteil
3-4
Rad
hat
Bestandteil
ist
Bestandteil
von
Die möglichen Eigenschaften von Links verallgemeinern die bereits bekannten
Eigenschaften von ER- oder objektorientierten Modellen. Und tatsächlich können
Links in RDBS ebenso wie Relationships als Attribute oder durch eigene Tabellen realisiert werden: m:n-Links mit zusätzlichen Attributen werden durch separate Tabellen realisiert, unidirektionale 1:1-Links können dagegen als zusätzliche
Attribute in der Tabelle der Quellenobjekte realisiert werden, wenn die Anzahl
der möglichen unidirketionalen Links, die von einem Objekt ausgehen können,
beschränkt ist (ansonsten benötigt man ebenfalls eine eigene Linktabelle).
Span-Links können entweder – wie in HTML – in die Dokumente selbst eingefügt
oder durch spezielle Positionsattribute realisiert werden: z. B. linkStartPos
89
Draft (2. März 2000)
und LinkEndePos. Die zweite Technik hat den Vorteil, dass man Teildokumentenicht nur von Textdokumenten, sondern von beliebigen Multimedia-Dokumenten als Linkquelle und/oder Linkziel einsetzen kann: Teilvideo- oder Teilaudio-Sequenzen, clickable images etc. Man beachte: Es ist in HTML zwar nicht
vorgesehen, dass sich mehrere Span-Links überlappen, aber dennoch ist dies –
zumindest in anderen Hypermedia-Systemen – ohne Weiteres vorstellbar.
Links können nicht nur in Tabellen gespeichert, sondern auch berechnet werden
(z. B. via JavaScript, Java und Forms). So wäre es z. B. möglich, neue (implizit
vorhandene Links) Links über mehrere Dokumente hinweg zu ermitteln.
statischer
Link
statischer
Link
aus statischen Links berechneter Link
5.4.1 Das Dexter-Referenz-Modell
1988 wurde im Dexter Inn, New Hampshire, USA das sogenannte Dexter Hypertext Referenz Modell entwickelt. Teilnehmer waren Entwickler verschiedener
Hypertextsysteme und verwandter Produkte, wie Intermedia, NoteCards, KMS
etc.
Ziele
– Standardterminologie
– Referenzmodell zur formalisierten Beschreibung bestehender HypertextSysteme
– Basis für die Entwicklung von Austauschformaten
Die Ergebnisse waren nicht nur auf Hypertext-, sondern sogar auf beliebig Hypermedia-Systeme anwendbar.
Im Dextermodell werden drei Schichten unterschieden:
1. Runtime Layer
Präsentationstools, Benutzer-Interaktion
2. Storage Layer
enthält das Netzwerk aus Dokumenten und Links
Draft (2. März 2000)
90
3. Within-Component Layer
enthält die Datenstrukturen und Inhalte der Dokumente
Der Within-Component Layer wird im Dexter-Modell nicht genauer spezifiziert,
das Hauptaugenmerk liegt auf dem Storage Layer, d. h. dem eigentlichen Netzwerk.
Im Dexter-Modell sind Links eigenständige Objekte, die eine Liste von Specifiern
enthalten: Jeder Specifier beschreibt einen Linkpfeil:
UID
Dokumentidentifikator
AID
Anchoridentifikator im Dokument
(jeder Anchor beschreibt ein Subdokument)
Direction Flag, mit 4 möglichen Werten: FROM, TO, BIDIRECT, NONE
presentation specification
(optional) Information über Präsentationsart (für Runtime Layer)
Mit der Presentation Specification kann z. B. angegeben werden, ob eine Animation abgespielt werden (z. B. student link) oder mit einem passenden Programm bearbeitet, d. h. editiert (z. B. teacher link) werden soll.
Dokumente sind entweder primitiv (sogenannte atoms) oder zusammengesetzte
aus anderen Dokumenten (composite objects).
Atom #275
Link #222
Composite #174
Component_Info
Attr1
...
Attrn
PresentationSpec
Anchors AID #1 Value
AID #2 Value
Component_Info
Attr1
...
Attrn
PresentationSpec
Anchors
Component_Info
Attr1
...
Attrn
PresentationSpec
Anchors AID #1 Value
Content
Specifier
Content
UID
#275
AID
#2
Direction From
PresentationSpec...
Atom #379
Atom #862
AID #1
Specifier
UID
#174
AID
#1
Direction To
PresentationSpec...
Specifier
..
.
91
Draft (2. März 2000)
Vorteile des Dexter-Modells:
– 1:n-, m:n-Links
– bidirektionale Links
– zusammengesetzte Objekte
– sehr mächtige Resolvefunktionen zur Linkverfolgung (boolsche Operationen etc.; Ergebnis ist Anchormenge)
– keine dangling references (ein Link der weg ist, ist weg – in allen Dokumenten!)
Nachteile des Dexter-Modells:
– Links auf Links sind erlaubt (absichtlich)
– die Linkrichtung steht nur im Link, nicht aber im Anchor
– keine Synchronisation von zeitkritischen Medien (Videos, Audio)
– der Within Component Layer wurde nicht spezifiziert (medienabhängige Datenmodelle fehlen)
Zwei Fragen an die Studenten:
1. Was kann man mit derartig mächtigen Links alles anstellen?
2. Wie realisiert man soetwas in einer Datenbank?
✎
´¶µR·a¸· ¹º»¼!½2·¾¿PÀ¥·ÁµRÂa¾œ¸·a¾Ã¿¥º¸ÄžÃÆRµRÂa¾¤À¥·a¸Ç¥ÃIÈYÂa¾·a»ˆÉ}ʺœ¹Œº»¼!½ÌË;¿PÀW·
µRÂS¾ÁÎ~µ ½ˆÏ¥·a»Ð!½2ºÏW·S»½2·a»·aµR»´o¿Š½2·a»Î~ÈYÏ¥·aÆRÆ·a»½„ÑÒµRÂw¼·aÆ ½)É
5.5 Koppelung WWW Ó
MMDBS
Es gibt mehrere Möglichkeiten, über WWW mit einem (MM)DB-System zu kommunizieren:
1. Via HTTP/CGI (Spezial-CGI-Programme wie PHP/FI oder Spezialserver wie
Oracle Web Server oder ÔÕ Web Server)
2. Direkt via HTTP mit Spezial-HTTP-Server
3. Direkt via Java (Spezialschnittstelle oder JDBC)
4. Via ActiveX o. ä.
Draft (2. März 2000)
92
benutzerdefinierte
HTTP-Ein-/AusgabeFilter (z.B. ISAPI)
InternetVerbindung
HTTP
statische
HTML-/
MMDokumente
HTTPServer
TCP/IP
SSI
Programmstart
WWW-Client
HTML-Interpreter
JavaScript
dynamisch
erzeugte
HTML-Seiten
JScript/VBScript
Java (JDBC)
ActiveX
statische
HTMLMasken
(server
parsed
HTML)
CGISkript/Programm
(PHP/FI,...)
Verbindungsaufbau
dauerhafte
Verbindungen
Verbindungsaufbau
TCP/IP
(Datenbank-)
Dämon
...
MMDBS
MMDBS
ad 1: Der wesentliche Nachteil dieser Lösung ist, dass für jeden DB-Zugriff ein
eigener CGI-Prozess gestartet werden muss.
ad 2: Das Problem der separaten CGI-Prozesse kann abgemildert werden, wenn
der aktuelle HTTP-Dämon direkt mit der gewünschten DB in Verbindung
treten kann. Allerdings bleibt das Problem bestehen, dass jeder Zugriff nicht
direkt, sondern über einen separaten Prozess – einen speziellen HTTP-Dämon – erfolgen muss.
ad 3: Den (vielfachen) Umweg über einen HTTP-Dämon kann man sich sparen,
wenn die Clients per Java direkt in Kontakt mit der gewünschten Datenbank
treten. In diesem Fall ist es möglich, dauerhafte Verbindungen für vollständige Datenbanksitzungen zu etablieren.
ad 4: Dies ist eine proprietäre Microsoft-Lösung, die im wesentlichen der Lösung
Nr. 3 entspricht.
Im Falle der Lösungen 1 und 2 gibt es fast immer einen oder mehrere Datenbankdämone, die eine dauerhafte Verbindung zu den gewünschten Datenbanken unterhalten. Damit wird vermieden, dass für jeden DB-Zugriff zunächst ein zeitauf93
Draft (2. März 2000)
wendiger DB-Login-Vorgang durchlaufen werden muss. Statt dessen loggt sich
jeder DB-Dämon lediglich ein einziges Mal in den gewünschten Datenbanken ein
und reicht anschließend alle Requests unter dieser Kennung an die Datenbanken
weiter. Der Nachteil dieser Lösung ist, dass nun der DB-Dämon, nicht mehr aber
das DBS selbst für die Benutzerverwaltung (Passwortschutz, Schreib- und Leserechtverwaltung etc.) zuständig ist.
Lediglich unter Java ist es möglich auf einen DB-Dämon mit speziellem Dummy-User zu verzichten, da dauerhafte Datenbankverbindungen aufgebaut werden
können.
5.5.1 JDBC
JDBC (Java DataBase Connectivity) ist eine standardisierte Schnittestelle, um
von Java-Programmen aus (insbesondere von Java-Applets aus) mit einer oder
mehreren Datenbanken zu kommunizieren.
JDBC unterstützt den Verbindungsaufbau, die Übermittlung von SQL-Statements
und die schrittweise Abarbeitung von Anfrageergebnissen.
Ein großes Problem von JDBC ist direkte Übermittlung von SQL-Befehlen an die
jeweilige Datenbank. Da sich der SQL-Sprachumfang von DBS zu DBS unterscheidet, können JDBC-Programme normalerweise nicht problemlos von einem
DBS auf ein anderes umgestellt werden. JDBC versucht dieses Problem mittels
sogenannter SQL-Escapes abzumildern.3 Zum Beispiel kann man Datumstrings
in der Form {d ’1998-09-13’} schreiben. Der jeweilige JDBC-Datenbanktreiber setzt diese Schreibweise in die (normalerweise nicht SQL2-konforme)
Schreibweise der zugehörigen Datenbank um. Die meisten der SQL-Escapes vermindern allerdings die Portabilität anstatt sie zu erhöhen, da von den DB-Herstellern nicht verlangt wird, dass sie alle SQL-Escapes einheitlich unterstützen.
Um das Portabilitätsproblem zumindest ein wenig in den Griff zu bekommen, fordert SUN von den Datenbankherstellern, dass ihre DBS mindestens den SQL2
Entry Level unterstützen. Nur mit dieser „Mindestausstattung“ kann der SUNKonformitätstest mit Erfolg absolviert werden und der JDBC-Treiber das Gütesiegel „JDBC compliant“ erhalten. Allerdings gibt es auch Treiber ohne dieses
Siegel (z. B. für PostgreSQL).
Einen weiteren Schritt zu mehr Portabilität stellen die (sehr vielen) verschiedenen boolsche Methoden dar, die eine Auskunft über die Fähigkeiten des aktuellen
DB-Systems geben:
supportsANSI92EntryLevelSQL()
3
Idee und Syntax stammen von ODBC (Open Database Connectivity) von Microsoft.
Draft (2. März 2000)
94
supportsSubqueriesInComparisons()
JDBC-Treiber
Es gibt verschiedene Arten von JDBC-Treiber:
1. datenbankspezifische Java-Erweiterungen von datenbankspezifischen
C/C++/ ¦$¦!¦ -Treibern (< 100 % Java, plattformabhängig, DB-abhängig)
2. datenbankunspezifische Java-Erweiterungen von ODBC-Treibern, sogenannte JDBC-ODBC-Bridges (< 100 % Java, plattformabhängig, relativ DB-unabhängig)
3. datenbankspezifische Java-Treiber (100 % Java, plattformunabhängig, DBabhängig)
4. datenbankunspezifische Java-Treiber von Drittherstellern plus sogenannte
Middleware (100 % Java, plattformunabhängig; die Middleware selbst muss
nicht in Java geschrieben sein – in diesem Fall läuft die Middleware auf speziellen Plattformen).
Java-Anwendung
JDBC-Schnittstelle
Java
JDBCTreiber
System A
Java
JDBCODBCBridge
C/C++
Treiber
System A
ODBCTreiber
System B
DBS A
DBS B
Java
JDBCTreiber
System C
Java
JDBCTreiber
Middleware
Middleware
DBS C
DBS D
ad 1: Diese Lösung kann vom Datenbankhersteller schnell implementiert werden,
ist allerdings nicht plattformunabhängig.
ad 2: Diese Lösung kann von Drittanbietern schnell implementiert werden, ist
aber nur eingeschränkt plattformunabhängig (abhängig von der Verfügbarkeit von ODBC-Treibern für viele Plattformen).
ad 3: Die Implementierung ist für den Datenbankhersteller aufwendiger. Allerdings ist der Treiber plattformunabhängig.
95
Draft (2. März 2000)
ad 4: Die Implementierung ist für Drittanbieter sehr aufwendig (wenn nicht auf
vorhandene Schnittstellen zurückgegriffen werden kann). Der Treiber selbst
ist plattformunabhängig, die Middleware dagegen meist plattformabhängig.
Ein Vertreter dieser Lösung stammt von OpenLink Software Ltd.
Openlink bietet nach oben hin sowohl einen JDBC- als auch einen ODBC-Treiber an. Auf der Datenbankseite werden mindestens folgende DBS
unterstützt: Oracle, Informix, CA Ingres, Sybase, Progress, Microsoft SQLServer, Unify, DB2, Solid und PostgreSQL. Im Internet ist eine Vollversion
mit Beschränkung auf zwei Benutzer gleichzeitig kostenlos erhältlich.
Servlets
Javaprogramme mit JDBC-Kopplung können nicht nur auf Clients laufen (sogenannte Applets), sondern auch auf Servern (sogenannte Servlets).
Vorteile von Servlets:
1. quasi-standardisierter DB-Zugriff (JDBC)
2. plattformunabhängig (modulo JDBC)
Allerdings muss der Server fähig sein Servlets auszuführen:
1. Server, die in Java implementiert wurden (Jeeves von Sun, Jigsaw von W3C).
2. Microsoft IIS bindet die Java Virtual Machine (JVM) von Sun ein (und nicht
etwa die vom Explorer!).
3. Für den Apache gibt es ein CGI-Programm (einen sogenannten CGI-Wrapper), der für jeden DB-Request die JVM von Sun startet. Eine bessere Lösung
gibt es alleridngs schon als Alpha-Release: Der Apache-Server startet einen
einzigen JVM-Prozess und lässt alle Servlets darin ablaufen.
Eine einfache JDBC-Anwendung
Im Wesentlichen muss jedes JDBC-Programm folgende Anweisungen ausführen:
<Laden eines JDBC-Treibers>
<Öffnen einer Datenbank>
While (!<Ende>)
{
<Senden einer SQL-Anweisung>
<Auslesen und Bearbeiten der Ergebnisse>
}
<Datenbank schließen>
Draft (2. März 2000)
96
package mysqltest
import java.sql.*;
class Test
{
public static void main()
throws java.lang.ClassNotFoundException,
java.sql.SQLException
{
// Einen oder mehrere JDBC-Treiber dynamisch, d. h. zur Laufzeit laden:
Class.forName("openlink.jdbc.Driver");
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
// Eine Datenbankverbindung aufbauen
// (der passende Treiber wird automatisch ermittelt):
Connection con =
DriverManager.getConnection
("jdbc:openlink://localhost/plz/DSN=dsn_postgres",
// "jdbc:odbc://whitehouse.gov:5000/Cat;PWD=Socks",
// "jdbc:odbc:corejava",
"Wolfgang",// username
"geheim", // password
);
// Nun kann für diese Verbindung ein Statement erzeugt werden:
Statement stmt = con.createStatement();
// SQL-Anfragen werden über Statementobjekte an die Datenbank geschickt;
// das Ergebnis dieser Anfragen sind Ergebnisobjekte:
ResultSet rs = stmt.executeQuery
("select * from Lieferant L" +
"where L.Name = ’Maier’"
);
ResultSetMetaData rsmd = rs.getMetaData();
// Nun kann das Anfrageergebnis verarbeitet werden:
// Als Ergebnis wird ein HTML-Dokument ausgegeben.
// Das heißt, dieses Programm könnte als Servlet laufen.
System.out.println ("<!DOCTYPE HTML PUBLIC ¦$¦!¦ >");
System.out.println ("<HTML>");
¦$¦$¦
97
Draft (2. März 2000)
System.out.println ("<TABLE>");
// Die Tabellenausgabe fängt mit dem Spaltennamen an
// (bei den Spaltennamen handelt es sich um "Metadaten"):
System.out.println ("<TR>");
for (int i=1; i<=rsmd.getColumCount(); i++)
system.out.println
("<TH>"+rsmd.getColumnName(i)+"</TH>");
System.out.println ("</TR>");
// Nun können die Ergebnistupel ausgegeben werden:
while (rs.next())
// Solange noch ein Tupel da ist
{
// (funktioniert auch bei leeren Ergebnissen)
System.out.println ("<TR>");
for (int i=1; i<=rsmd.getColumnCount(); i++)
System.out.println("<TD>"+rs.getObject(i)+"</TD>");
// rs.getObject(getColumnName(i)) funktioniert auch
System.out.println ("</TR>")
}
// Die Tabelle ist fertig:
System.out.println ("</TABLE>");
// Nun heißt es aufräumen
// (man könnte diese Arbeit auch dem garbage Collector überlassen):
rs.close();
// Ergebnis-Cursor schließen
stmt.close();
// Statement schließen
con.close();
// Datenbankverbindung schließen
};
};
Draft (2. März 2000)
98
Kapitel 6
Objektorientierte
Datenbanken
OODBS bieten viele objektorientierte features:
– Objektidentifikatoren
– Vererbung
– Methoden
– Kapselung
– etc.
Insbesondere ist einer der wesentlichen Einschränkungen von RDBS in OODBS
aufgehoben worden: Tabellen müssen nicht mehr in 1NF vorliegen.
Derzeit gibt es zwei wesentliche Bemühungen, OODBS zu standardisieren:
– SQL3, ein ISO/ANSI-Standard
– ODMG, ein Industriestandard (kein offizieller Standard)
Für die Praxis derzeit wichtiger ist allerdings der ODMG-Standard, da er von einigen DB-Herstellern bereits rudimentär unterstützt wird. SQL3-fähige DB-Systeme werden wohl noch einige Zeit auf sich warten lassen. Derzeit sind die DB-Hersteller vollauf damit beschäftigt SQL2-(full level)-DB-Systeme zu implementieren.
6.1 ODMG
ODMG (Object Database Management Group) ist eine Untergruppe der OMG
(Object Management Group). In der OMG sind 500 Institutionen und Firmen vertreten.
Ziel der OMG ist es, eine Referenzarchitektur für verteilte Objektsysteme zu
schaffen.
99
Draft (2. März 2000)
Mehrere Hersteller von OODBS (wie O2, Objectivity, ONTOS, Versant etc.) haben sich Anfang der 90er in der ODMG zusammengeschlossen um kurzfristig
einen Standardisierungsvorschlag für OODBS zu erarbeiten.
1993: Standardisierungsvorschlag ODMG-93, Version 1.0
1994: Standardisierungsvorschlag ODMG-93, Version 1.1
1995: Standardisierungsvorschlag ODMG-93, Version 1.2
1997: Standardisierungsvorschlag ODMG 2.0
Die Vorteile des ODMG-Standards:
– kurz, verglichen mit SQL3 (wenige 100 Seiten vs mehrere 1000 Seiten)
– es gibt bereits Teilimplementierungen
– OQL ist stark an das Select-Statement von SQL angelehnt
Die Nachteile des ODMG-Standards:
– Er ist inkonsistent, ungenau und unvollständig (da sehr kurz gehalten), oft
wird nur die Syntax nicht aber die Semantik beschrieben.
– Die neueren Versionen sind nicht abwärtskompatibel (Konzepte werden in
neueren Versionen geändert oder entfallen ganz, die Semantik wird geändert
etc.).
– Die Definition der ODMG-Konformität (ODMG-compliant) ist herstellerfreundlich aber untauglich: Sobald eine von vier (von derzeit fünf) Teilkomponenten in einer OODBS implementiert wurde und der Hersteller dies
bei der ODMG meldet, gilt das OODBS als ODMG-konform. Es gibt auch
noch das Gütesiegel ODMG-zertifiziert (ODMG-certified), das bislang jedoch noch kein OODBS erhalten hat.
ODMG 2.0 besteht aus folgenden Komponenten:
– ODL (Object Definition Language, analog zu DDL)
– OQL (Object Query Language, select analog zu DML)
– C++-Sprachanbindung
– Smalltalk-Sprachanbindung
– Java-Sprachanbindung (neu, nicht Bestandteil der Konformitäts-Definition)
Achtung: OQL ist immer noch nicht berechnungsvollständig (keine rekursiven
Views, kein While o. ä.).
ODMG 2.0 unterstützt:
Draft (2. März 2000)
100
Objekte, Werte (Literale genannt), Klassen (Typen genannt) mit und ohne
Extension, Attribute, Methoden (Operationen genannt), Beziehungen, Vererbung (ISA-Hierarchien ohne Mehrfachvererbung und Implementierungshierarchien mit Mehrfachvererbung).
Der Nullwert heißt in ODMG nil. Die Semantik entspricht der Nullwertsemantik
von SQL2. Allerdings ist es nicht möglich, einen Datentyp als not null zu
deklarieren.
6.1.1 Primitive Datentypen
ODMG unterstützt die üblich primitiven Datentypen:
– Float, Boolean, String, Enum etc.
Außerdem unterstützt ODMG in Anlehnung an SQL2 folgende Datentypen:
– Date, Interval, Time, Timestamp
6.1.2 Komplexe Datentypen
ODMG unterstützt folgende komplexe Datentypen (wobei t ein beliebiger Datentype sei):
Set<t>
mengenwertige Objekte
Bag<t>
multimengenwertige Objekte
List<t>
listenwertige Objekte, insbesondere String und Bit_String
Array<t> ähnlich wie List<t>, allerdings kann es leere Feldelemente geben,
d. h. Feldelemente deren Wert gleich Nil ist und die die Bedingung
is_defined( ¦$¦$¦ ) erfüllen
Dictionary<k,t>
Assoziatives Array mit Schlüsseltyp k
Diese Datentypen liefern Objekte als Ergebnis, d. h. eine Menge, ein Bag, eine
Liste etc. ist ein Objekt. Für diese Objekte gibt es eine Reihe von Methoden:
cardinality()
Anzahl enthaltener Elemente
is_empty()
Test: Container ist leer
contains_element() Test: Element enthalten
insert_element()
Element einfügen
101
Draft (2. März 2000)
remove_element()
Element löschen
create_iterator()
Erzeugt einen Iterator zum Abklappern der einzelnen Elemente (Iteratormethoden: not_done(),
reset(), get_element(), advance(), etc.)
Für Mengen (set<t>) gibt es noch weitere Methoden:
union_with()
intersection_with()
difference_with()
is_subset_of()
is_proper_superset_of()
Ebenso gibt es für die übrigen Container-Datentypen spezielle Methoden.
Denselben Satz an Container-Typen gibt es nochmal als Werttypen, d. h., in diesem Fall sind Mengen, Bags, Listen etc. Werte ohne OIDs. Zusätzlich gibt es den
komplexen Werttyp (aber komischerweise nicht den Objekttyp) struct:
struct< Ö× ¨ Ø !× ¯ ¦$¦$¦ ¯iÖÙ ¨ Ø Ù >
Mit Hilfe dieser Datentypen lassen sich insbesondere Tabellen beschreiben:
¨ Ø J× ¯ ¦!¦$¦ ¯iÖÙ |¨ Ø Ù >>
set<struct< Ö× |
Diese Tabellen müssen aber nicht 1NF sein:
set<struct<Name: string, Telefon: list<string>>>>
"Wolfgang" ["325","450"]
"Marianne" []
Außerdem gibt es weitere Arten von Tabellen:
Tabellen mit Duplikaten bag<struct< ¦!¦$¦ >>
geordnete Tabellen list<struct< ¦$¦$¦ >>
geordnete Tabellen mit Leerzeilen array<struct< ¦$¦!¦ >>.
Die Modifikation von Objekten (und damit auch von Tabellen) erfolgt in ODMG
prozedural und nicht etwa deklarativ wie in SQL. Zu diesem Zweck kann man
Methoden wie insert_element() einsetzen oder neue Methoden definieren. Operationen werden in der ODL (siehe nächster Abschnitt) deklariert, nicht
aber definiert. Die Definition erfolgt in einer Host-Sprache (derzeit entweder
C++ oder Java oder Smalltalk), die über eine standardisierte ODMG-Schnittstelle (C++-Bindung, Java-Bindung oder Smalltalk-Bindung) an ein ODMS-Datenbanksystem gekoppelt ist.
Draft (2. März 2000)
102
Leider ist es in der ODL nicht möglich Anfrage- und Modifikationsmethoden zu
unterscheiden. Das heißt, wenn man eine Methode für ein Objekt aufruft, kann
man nie sicher sein, dass sich dadurch das Objekt nicht verändert. Die Operationsparameter werden mit den Schlüsselwörtern in, out, inout markiert, um
Input- und/oder Output-Parameter zu definieren.
Zum Beispiel:
Integer add (in Integer x);
6.1.3 ODL
Die wesentliche Aufgabe der Objekt Definition Language (ODL) ist es, Klassen
zu definieren.
Ein objektorientiertes Datenmodell kann sehr einfach auf eine Menge von Klassendefinitionen abgebildet werden. Das heißt, ODMG-Klassendefinition entsprechen den SQL-Tabellendefinitionen. Allerdings gehört zu jeder SQL-Tabellendefinition automatisch auch eine Datenbanktabelle, in der die zugehörigen Tupel
abgelegt werden. Es wird also nicht zwischen Schema und Extension unterschieden. In ODMG kann dagegen für jede Klasse explizit angegeben werden, ob ein
geeigneter Container zur Verwaltung der Klassenextension angelegt werden soll
oder nicht. Man beachte, dass auch für Klassen ohne Extension Objekte erzeugt
werden können. Diese müssen allerdings immer als Bestandteil anderer Objekte
gespeichert werden. Dies ist möglich, da ODMG-Objekte nicht in 1NF vorliegen
müssen.
In ODMG werden zwei Arten von Klassen unterschieden: interfaces und classes.
Ein Interface ist wie folgt aufgebaut:
interface <Name> [:<Superinterfaces>+]
{
<Attribute>
<Relationships>
<Methodendeklarationen (= Operationendeklarationen)>
}
Ein Interface legt also die üblichen Eigenschaften von Objekten fest. Dabei fällt
auf, dass Mehrfachvererbung unterstützt wird und Beziehungen (Relationship) mit
Hilfe einer besonderen Art von Attributen und nicht etwa mit Hilfstabellen oder
Hilfsklassen (wie in SQL) realisiert werden.
Eine Klasse ist wie ein Interface aufgebaut, kann aber noch zusätzlich eine
Klassenvererbung, eine (transiente = flüchtige oder persistente = dauerhafte)
103
Draft (2. März 2000)
Klassenextension und Schlüsselattribute definieren. Dabei wird seit der Version
ODMG 2.0 Klassen-Mehrfachvererbung nicht mehr unterstützt.
class <name> [extends <class>]
[: <superinterfaces>+]
([extend <Name der Extension>]
[key[s] <Schlüsselkandidat>+]
)[transient/persistent]
{
<Attribute>
<Relationships>
<Methodendeklarationen>
}
Eine Menge von Interface- und Klassendefinition wird zu einem Modul zusammengefasst. Außerdem können Module Konstantendefinitionen, Typdefinitionen
und Ausnahmedefinitionen enthalten. Das Klassenhierarchie
Mitarbeiter
0..*
hat_Untergebene
hat
Chef
0,1
hat_Chef
kann beispielsweise als folgendes Modul realisiert werden:
module Firma
{
const Stringlaenge = 20;
deftype struct TAdresse
{
string<Stringlaenge> Strasse;
¦$¦$¦
}
exception AbteilungGibtEsNicht
{
string FehlerMeldung;
string FalscherName;
Draft (2. März 2000)
104
¦$¦$¦
}
interface Person_IF
{
attribute string Name;
attribute string Abteilung;
attribute TAdresse Adresse;
attribute list<String> Tel;
}
class Mitarbeiter: Person_If
(extent EMitarbeiter
key
MitarbeiterNr
)
{
readonly attribute string MitarbeiterNr;
relationship Chef hat_Chef
inverse Chef::hat_Untergebene;
void NeueAbteilung (in string Abteilung)
raises AbteilungGibtEsNicht;
}
class Chef extends Mitarbeiter
(extent EChef)
{
relationship set<Mitarbeiter> hat_Untergebene
inverse Mitarbeiter::hat_Chef
}
}
Methoden werden – wie bereits erwähnt – nicht in ODL, sondern in einer Hostsprache implementiert. Dabei können geerbte Methoden – wie NeueAbteilung – natürlich überschrieben werden. So sollte die Methode NeueAbteilung bei Chefs nicht nur das Attribut Abteilung, sondern auch das Attribut hat_Untergebene aktualisieren. Man beachte, dass jede Modifikation des Relationship-Attributs hat_Untergebene auch eine Modifikation
der zugehörigen inversen Relationship-Attribute hat_Chef zur Folge hat (und
umgekehrt). Wenn beispielsweise hat_Untergebene (z. B. mittels remove_element) geleert wird, muss bei allen betroffenen Mitarbeitern nil als
Wert von hat_Chef eingetragen werden. Die neuen Untergebenen eines Chefs
105
Draft (2. März 2000)
können anschließend abhand des neuen Abteilungsnamens aus der Extension
EMitarbeiter ermittelt werden.
Objekterzeugung
Für jede Klasse C existiert ein Konstruktor C(<Attr1>:<Wert1> ¦$¦$¦ ). Objekte
haben einen eindeutigen OID. Zusätzlich können Ihnen externe Identifikatoren
(EIDs) zugewiesen werden.
6.1.4 OQL
Neben den speziellen Hostsprachanbindungen (C++-Bindung etc.) unterstützt
ODMG auch noch eine sprachunabhängige (Ad-hoc-)Anfragesprache: OQL. Diese Sprache orientiert sich stark an SQL2, ist jedoch viel flexibler, da die Beschränkung auf 1NF entfällt.
In OQL gibt es neben Select-Statements, deren Syntax im Wesentlichen
eine Erweiterung der SQL2-Syntax darstellt, noch andere Arten von Anfragen
(Queries):
– Konstanten, wie nil, true, false, 1, 3.14
– Benutzerdefinierte Konstanten
– Ausdrücke, wie 3+4, (a+5)*6, (a or b) and not c, 4<=e,
a*element(select ¦$¦$¦ from $¦ ¦!¦ where)
– Containerkonstruktoren (set(<query>+) etc. ),
wie set(1,2,3,3), bag(set(1),set(1),set(1,2)),
struct(a: 4, b: set(2,3))
– Funktionsaufrufe, wie fac(6), f(set(1), select ¦$¦$¦ )
– Pfadzugriffe, wie Wolfgang.Adresse.Strasse,
Wolfgang.Kinder(3)
– Mengenverarbeitung, wie
Ú for all <var> in <query>: <query2>
Ú exists <var> in <query>: <query2>
Ú exists (<query>)
Ú unique (<query>)
Ú <query> in <query>
Ú <query> <|<=| ¦$¦!¦ some|any|all <query>
Ú count(<query>), count (*)
Ú sum(<query>), min, max, avg
Draft (2. März 2000)
106
– Mengenoperationen, wie intersect, union, except, in
– Konversionsfunktionen wie listtoset, element (Konvertierung einer
einelementige Menge zu ihrem Element, z. B. element(set(3))=3),
distinct (Duplikatelemination), flatten (die erste Klammerebene
wird entfernt)
z. B.:
flatten(list(list(1,2),set(3,3,4),bag(3,3))=
list(1,2,3,4,3,3)
Die Select-Anweisung sehen im Prinzip genauso aus wie in SQL2, mit dem
wesentlichen Unterschied, dass in den einzelnen Klauseln beliebige Queries (vom
jeweils passenden Typ) stehen dürfen. Der Ergebnistyp eine Selectanweisung ist
entweder bag< ¦!¦$¦ > (select ¦$¦$¦ ) oder set< ¦!¦$¦ > (select distinct ¦!¦$¦ )
oder list< ¦$¦$¦ > (select ¦!¦$¦ order by ¦$¦$¦ )
Auch ist es in OQL möglich, Views zu definieren (allerdings wiederum keine
rekursiven Views):
define <Viewname> as <query>
Beispielsanfragen
select distinct Name, Tel from Mitarbeiter
Ergebnistyp:
set<struct<string Name, list<string> Tel>>
Ergebnismenge:
set(struct(Name: "Wolfgang", Tel: list("325","450")),
struct(Name: "Marianne", Tel: list())
¦$¦$¦
)
Alternative Schreibweise:
select distinct struct(Name: m.Name, Tel: m.Tel)
from Mitarbeiter as m
Weitere Möglichkeiten:
select struct(Name: m.Name,
Tel: (select * from m.Tel as y
where y like "089%")
)
from Mitarbeiter as m
107
Draft (2. März 2000)
select m.Adresse.Ort
from Chef as p, p.hat_Untergebene as m
where p.Name="Hinterhuber"
An diesem Beispiel sieht man, dass durch die NFNF-Struktur der Klasse Chef,
die explizite Angabe eine Joinbedingung nicht mehr notwendig ist. Dies ist einer
der Hauptgründe für die Argumentation, dass OODBS wesentlich effizienter als
RDBS seien. Allerdings ist das i. Allg. ein Trugschluss. Einerseits kann man in
manchen RDBS sogenannte Clusterindexe zum Beschleunigen bestimmter Joinoperation definieren, andererseits kommt man auch in OODBS nicht an expliziten
Joins vorbei, wenn Anfragen gestellt werden, die „quer“ zur Objekthierarchie liegen:
select struct(Mitarbeiter: m1, Kollege: m2)
from Mitarbeiter as m1, Mitarbeiter as m2
where m1.Gehalt < m2.Gehalt
Man beachte, dass es auch viele Nicht-Select-Anfragen gibt:
(3*4+27)/5
Geschaeftsfuehrer // EID eines Objektes der Klasse Chef
Mitarbeiter
// Ein mengenwertiges Objekt
Geschaeftsfuehrer.Adresse.Strasse.Hausnummer.Stockwerk
count(Geschaeftsfuehrer.hat_Untergebene)
count(select p
from Geschaeftsfuehrer.hat_Untergebene p
where p.Adresse.Ort = "Augsburg")
Anmerkung: Die SQL2-Schreibweise select count(p) ¦$¦$¦ wird auch unterstützt.
for all p in Chef: p.Gehalt>100000 // true oder false
Anmerkung 2: OQL unterstützt im Gegensatz zu SQL exists und for all!
Man kann auch neue Datentypen definieren und die zugehörigen Konstruktoren
in Anfragen einbeziehen.
Zum Beispiel:
typedef struct KurzAdresse {String Ort};
typedef set<KurzAdresse> Kurzadressen;
Kurzadressen(select Kurzadresse(Ort: p.Ort)
from Mitarbeiter)
Da Funktions- und Methodenaufrufe spezielle Anfragen sind, kann man diese ohne besondere Vorkehrungen ausführen oder in komplexere Anfragen einbauen.
Draft (2. März 2000)
108
select p.Alter() from Mitarbeiter p
select p.Alter("1998/05/05") from Mitarbeiter p
Hier sei Alter() eine Methode, die das Alter eines Mitarbeiters mit Hilfe des
aktuellen Datums oder des angegebenen Datums und des Geburtstages des Mitarbeiters berechne.
Anmerkung: Über Objektmodifikation und insbesondere die Effekte, die der Aufruf von Updatemethoden in Select-Statements hat, wird im ODMG-Standard
nichts gesagt. Updatemöglichkeiten werden nur für die C++-Bindung (C++ OML)
beschrieben – auf einer einzigen Seite. Dabei ist es gerade die Semantik von Updateoperationen, die im Falle von deklarativen Sprachen wie SQL und OQL die
meisten Probleme verursacht.
109
Draft (2. März 2000)
Draft (2. März 2000)
110
Kapitel 7
Normalformtheorie
7.1 Funktionale Abhängigkeit
Û „« Ü $× ¯ ¦$¦$¦ ¯ Ü Ùs¬ ein Relationenschema Û
mit den Attributen
$
¦
$
¦
¦
@
­
Ý
×
$
¯
¯
Ù
s
Þ
.
Ü
Ü
Ü
Eine Attributmenge ß6à Ü heißt funktional abhängig (functional dependent) von
einer Attributmenge áà Ü , in Zeichen á<ª ß , wenn gleiche Attributwerte für
á auch gleiche Attributwerte für ß erzwingen.
Es
sei
Beispiel
Liefer
Lieferant Adresse
Artikel
Preis
’Mayer’
’Königsbrunn’ ’PIII500’ 500
’Mayer’
?
’PIII600’ 1200
Wenn
die
Adresse
funktional
vom
Lieferant
abhängt
(Lieferant ª Adresse), dann muss der Wert von ? gleich ’Königsbrunn’ sein.
Bestimmte funktionale Abhängigkeiten können zu sogenannten Update-Anomalien führen.
– Update-Anomalie
Die Änderung der Adresse von Mayer muss in jedem Tupel geschehen.
– Insert-Anomalie
Die Adresse von Mayer kann nicht erfasst werden, wenn Mayer (noch)
nichts liefert.
– Delete-Anomalie
Löscht man das gesamte Liefersortiment von Mayer (z. B. bei einer Produktumstellung), verliert man seine Adresse.
Ziel der Normalformtheorie ist es, Anomalien, die durch redundante Speicherung
von Fakten entstehen, zu vermeiden.
Im Folgenden werden wir uns auf Redundanzen, die sich durch funktionale Abhängigkeiten ergeben beschränken.
111
Draft (2. März 2000)
7.1.1 Reduzierte funktionale Abhängigkeiten
Eine funktionale Abhängigkeit á6ª
Ö heißt reduziert, wenn
1. Ö ein einzelnes Attribut ist
ã
2. Ö â á ( ¦$¦!¦ Öä $¦ ¦$¦ ªåÖsä gilt nämlich immer)
3. Für keine echte Teilmenge á'æç:á gilt á'æª Ö
( Ö heißt in diesem Fall voll funktional abhängig von á )
Jede Menge von funktionalen Abhängigkeiten (kurz FD-Menge) kann in eine
äquivalente (gleichwertige) Menge von reduzierten funktionalen Abhängigkeiten
(kurz rFD-Menge) umgewandelt werden.
Wenn in einer rFD-Menge keine funktionale Abhängigkeit aus anderen berechnet
werden kann (wie in Ü ª áè¯á<ª ßêé Ü ª ß ), spricht man von einer minimalen Überdeckung.
7.1.2 Schlüsselkandidaten
Eine Menge ëìà Ü von Attributen heißt Schlüsselkandidat von Û , wenn alle Attribute von Û voll funktional von ë abhängig sind.
Ein Attribut Ö , das zu keinem Schlüsselkandidaten gehört, heißt Nichtschlüssel-Attribut, alle anderen Attribute heißen Schlüssel-Attribute.
7.2 Normalformen
7.2.1 Erste Normalform (1NF)
Im Weiteren nehmen wir an, dass alle Attribute primitive Domänen (wie Bool,
Varchar, Integer etc.) anstelle von komplexen Domänen (wie Set, List,
Tupel etc.) haben.
Wie bereits bekannt ist, spricht man in diesem Fall von erster Normalform (1NF).
In RDBS ist diese Bedingung immer erfüllt, in ODBS dagegen nicht.
7.2.2 Zweite Normalform (2NF)
Eine rFD-Menge í erfüllt die zweite Normalform (2NF), wenn für alle
î6ïñðóò
ð
î
í mit Nichtschlüssel-Attribut gilt, dass ein Schlüsselkandidat ist
î
oder ein Nichtschlüsselattribut enthält. Das heißt, es gibt kein Nicht-Schlüsselattribut, das voll funktional abhängig von einem echten Teilschlüssel ist.
Draft (2. März 2000)
112
Beispiel
Das Relationenschema
Lieferant Artikel Adresse Preis
ï
mit Lieferant
Adresse ist nicht in 2NF, da Lieferant kein Schlüsselkandidat ist (sondern Lieferant, Artikel), wohl aber ein Schlüsselattribut
und da Adresse ein Nicht-Schlüssel-Attribut ist.
Die Relationenschemata
Lieferant Adresse
Lieferant Artikel, Preis
Lieferant
ï
Adresse
sind dagegen in 2NF.
7.2.3 Dritte Normalform (3NF)
Eine rFD-Menge í erfüllt die dritte Normalform (ist in 3NF), wenn für alle
î6ïñðóò
ð
î
í mit Nichtschlüssel-Attribut gilt, dass ein Schlüsselkandidat ist.
Diese Normalform ist strenger als 2NF, da Nichtschlüssel-Attribute nur noch von
Schlüsselkandidaten abhängen dürfen, nicht mehr aber von Nichtschlüsselkandidaten:
3NF ô
2NF ( ô
1NF)
Beispiel
Das Relationenschema
ï
Artikelnr DMPreis EuroPreis
1
2
1,96
1,96
DMPreis
ï EuroPreis
EuroPreis
DMPreis
1,00
1,00
ist nicht in 3NF (wohl aber in 2NF).
Die Relationenschemata
Artikelnr EuroPreis
EuroPreis DMPreis
EuroPreis
ï
DMPreis
ï
DMPreis
EuroPreis
oder
Artikelnr DMPreis
DMPreis
Europreis
ï
DMPreis
ï EuroPreis
EuroPreis
DMPreis
sind dagegen alle in 3NF.
113
Draft (2. März 2000)
7.2.4 Boyce-Codd-Normalform (BCNF)
Eine rFD-Menge í erfüllt die Boyce-Codd-Normalform (ist in BCNF), wenn für
î6ï ðœò
î
alle
í gilt, dass ein Schlüsselkandidat ist.
Diese Normalform berücksichtigt – im Gegensatz zu 2NF und 3NF – auch Abhängigkeiten zwischen Schlüsselattributen. Es gilt also:
BCNF ô
3NF ô
2NF ( ô
1NF)
Beispiel
Das Relationenschema
Stadt
Straße
Postleitzahl
Königsbrunn Blumenallee 86343
? (Redundanz) Lilienstraße 86343
ï
ï
Stadt,Straße
Postleitzahl, Postleitzahl
Stadt
ist in 3NF (da es gar keine Nichtschlüsselattribute gibt), aber nicht in BCNF.
Grund: Es gibt zwei Schlüsselkandidaten:
Stadt, Straße und Straße, Postleitzahl
Das Attribut Postleitzahl alleine ist allerdings kein Schlüsselkandidat.
Das Relationenschemata
Stadt, Straße
Straße, Postleitzahl
sind in BCNF. Nun können allerdings die funktionalen Abhängigkeiten des Ausgangsschemas nicht mehr gewährleistet werden (außer, wenn beide Tabellen immer gleichzeitig und dann konsistent modifiziert werden).
7.3 Zerlegung (Dekomposition) eines Relationenschemas
Ein gegebenes Relationenschema õ kann bzgl.. einer Menge í immer so in Relationenschemata õoö!÷$ø$ø!ø$÷õù zerlegt werden, dass folgendes gilt:
1. õoö!÷$ø$ø!ø$÷õù sind – je nach Wunsch – in 2NF, 3NF oder BCNF
2. Für jede Relation ú , die í
erfüllt, gilt újû=üýþ$ÿ„úø$ø$ø~üýÿ`ú
Die zweite Bedingung heißt lossless-join- oder nonadditive-join-Eigenschaft. Sie
besagt, das man mit Hilfe von (Natural)joins die ursprüngliche Relation aus den
zerlegten Relationen berechnen kann.
Draft (2. März 2000)
114
Man beachte, dass diese Bedingung nicht für jede beliebige Zerlegung gilt:
õ
Mitarbeiter Alter Tel
Anton
38
427
Berta
38
305
õoö Mitarbeiter Alter
Anton
Berta
õ
Alter Tel
38
38
38
38
427
305
õoö õ
Mitarbeiter Alter Tel
Anton
Anton
Berta
Berta
38
38
38
38
427
305
427
305
Die angegebene Zerlegung ist nicht möglich, da eine funktionale Abhängigkeit
ï
Tel nicht existiert.
Alter
Algorithmus 3NF-Dekomposition
Gegeben seien ein Relationenschema õ zusammen mit einer Menge í von funktionalen Abhängigkeiten. Alle Attribute sollten in irgndeiner (wenn auch nicht
notwendigerweise funktionalen) Beziehungen zu anderen Attributen stehen. Sollte es Attribute ohne irgendeine Beziehung zueinander geben (wie z. B. Geburtstag, KByte, AnzahlReserveRäder), so sollten õ und í vorher in
mehrere Teilschemata aufgespalten werden.
3NF-Dekomposition ( õ ,í ):
1. Erzeuge für jede Abhängigkeit
îêï
ðèò
í das Relationenschema
îÍð
.
2. Wenn keines der erzeugten Relationenschemata einen vollständigen Schlüsselkandidaten enthält, wähle einen Schlüsselkandidaten aus und füge ihn als
eigenes Schema hinzu.
3. Entferne Schemata, die Teil eines anderen Schemas sind.
4. Fasse Relationenschemata mit gleichen Schlüsselkandidaten zu einem Schema zusammen (sofern zwischen den Nicht-Schlüssel-Attributen keine funktionalen Abhängigkeiten bestehen).
S A, S B û S A B
Algorithmus BCNF-Dekomposition
îêïåð
die BCNF-Eigenschaft von õ:û*ö!÷$ø$ø$øJ÷où verletzt, zerlege õ in
ð
õoöPû3õ
und
Wenn
115
Draft (2. März 2000)
õ û
îÍð
und zerlege die resultierenden Schemata weiter:
BCNF-Dekomposition ( õ ö ÷ )
BCNF-Dekomposition ( õ ÷ )
Beispiel
V
P
H
R
S
N
Vorlesung
Professor
Stunde (+ Tag)
Raum
Student
Note
ï
P
V
R
R
N
V
HR
HP
HS
VS
ï
ï
ï
ï
Ein Professor pro Vorlesung
höchstens eine Vorlesung pro Stunde und Raum
Ein Professor kann zur selben Zeit nicht an zwei Orten sein
Auch Studenten sind unteilbar
Ein Student hat eine Note pro Fach
3NF-Dekomposition
VP HRV HPR VSN HSR
Schlüsselkandidaten
V
HR
HP
VS
HS
ï
ï
ï
ï
ï
VP
HRVP
HPRV
VSNP
HSRVPN
HS ist in HSR bereits enthalten, damit ist das obige Schema das gesuchte 3NFSchema. Es ist nicht ideal, da dies Lossless-join-Dekomposition von R auch mit
einigen echten Teilmengen dieses Schemas erreicht wird ( ô Redundanz). Man
kann aber auf keine Tabelle verzichten, wenn man alle Abhängigkeiten berücksichtigen will.
BCNF-Dekomposition
VPHRSN
ï
V
P: V ist kein Schlüsselkandidat
VHRSN VP
Draft (2. März 2000)
116
ï
HR
HRSN
ï
HP
ï
VS
ï
HS
HRSN
V:
HRV
R:
N:
R:
HRV
HR ist kein Schlüsselkandidat
VP
entfällt
entfällt
HS ist ein Schlüsselkandidat
VP
Dies ist ein BCNF-Schema, aber ein schlechtes. Zum Beispiel ist die Note nicht
bei der zugehörigen Vorlesung, zwei Abhängigkeiten werden gar nicht mehr beachtet.
Beispiel 2
Stadt Straße PLZ
ï
ï
Stadt Straße
PLZ, PLZ
Stadt
3NF-Dekomposition
Stadt Straße PLZ
PLZ
Stadt
Das zweite Schema entfällt, da es Teil des ersten ist.
BCNF-Dekomposition
ï
Stadt, PLZ ist kein Schlüsselkandidat
PLZ
Stadt Straße
PLZ
Stadt
Fazit
Die Zerlegung (Dekomposition) eines Relationenschemas in 3NF-Schemata (und
damit auch in 2NF-Schemata) bewahrt alle funktionalen Abhängigkeiten, ist also
abhängigkeitserhaltend. BCNF ist dagegen nicht abhängigkeitserhaltend (Integritätsbedingungen fallen weg) vermeidet aber – in seltenen Spezialfällen – mehr
Redundanz und damit Updateanomalien. In manchen Fällen verzichtet man aus
Effizienzgründen auf vollständige 3NF- oder BCNF-Normalisierung.
7.3.1 weitere Normalformen
Funktionale Abhängigkeiten sind nicht die einzigen Abhängigkeiten zwischen Attributen, die zu redundanter Speicherung führen. Es gibt weitere Abhängigkeiten,
wie
– Mehrwertige Abhängigkeiten ( ô
4NF)
117
Draft (2. März 2000)
– Join-Abhängigkeiten ( ô
5NF)
– Abhängigkeiten zwischen Relationen (bislang keine Normalformen)
– etc.
Jede weitere Normalform sollte die bekannten Normalformen verallgemeinern.
Es gilt z. B.
5NF ô
4NF ô
BCNF ô
2NF ô
1NF
Das heißt, jede weitere Normalform zerschlägt ein Relationenschema in immer
mehr, kleinere Teilrelationen.
Vorteil:
Redundanzvermeidung, Anomalienvermeidung
Nachteil: Effizienzprobleme durch mehr Joins
In der Praxis ist 3NF (und manchmal sogar 2NF) fast immer ausreichend. Schemata, die zwar 3NF, aber nicht BCNF sind, kommen in der Praxis so gut wie nicht
vor (z. B. ist das obige Beispiel nicht praxisgerecht, da beide Abhängigkeiten in
der Praxis nicht gelten).
7.4 Normalformen und ER-Modellierung
Entityschemata mit einem künstlichen Schlüsselattribut (wie z. B. Personalnr)
sind automatisch in 2NF, wenn es keine weiteren Schlüsselkandidaten gibt: Jedes
Attribut ist voll funktional abhängig vom Primärschlüssel.
In der Praxis gibt es meist auch keine weiteren Schlüsselkandidaten. So wird eine
Person unter Umständen noch nicht einmal durch
Name Vorname Geburtsdatum Adresse
eindeutig identifiziert (z. B. zwei Meier, Sepps, geb. 1.1.1960, wohnhaft in demselben Hochhaus).
Sollte es einen weiteren Schlüsselkandidaten geben, so sollte man diesen – im
Sinne von BCNF – zusammen mit dem (künstlichen) Primärschlüssel in einer
eigenen Tabelle speichern.
Abhängigkeiten zwischen Nichtschlüsselattributen sollten – gemäß 3NF – vermieden werden.
Nicht
Draft (2. März 2000)
118
Ware
Wnr
DMPreis
EuroPreis
sondern
Ware
0..*
Preis
1 Umrechnung
Wnr
Euro
DM
oder gar
Ware
Wnr
EuroPreis
DMPreis()
Das heißt, DMPreis als Methode (= Funktion). In diesem Fall ist nämlich sogar eine mathematische Funktion zur Berechnung der funktionalen Abhängigkeit
bekannt.
1 DM = 1 Euro : 1,95 gerundet auf zwei Stellen
Diese „Methode“ wird aber vermutlich nicht in SQL ausgeführt (keine Rundungsoperatoren), sondern in einer Hostsprache (Java, C++ etc.).
Beziehungen haben mindestens zwei Schlüsselattribute. Funktionale Abhängigkeiten, die sich nicht auf alle Foreign Keys beziehen, sind i. Allg. auf Designfehler
zurückzuführen.
Student
0..*
0..* Fach
Name
Matnr
Klausur
Prüfer
Studentenname
Prüfung
Student Fach Prüfer Studentenname
119
Draft (2. März 2000)
Student
ï
Studentenname ô
nicht 2NF
Designfehler: Der Studentenname gehört zum Studenten
Mehrwertige Abhängigkeiten entstehen i. Allg. durch mengenwertige Attribute
Name
Hobbies Geburtstagsjahr
Wolfgang {Tischtennis,
1961
Akkordeon,
Fahrrad}
ô
1NF-Form
Wolfgang Tischtennis 1961
Wolfgang Akkordeon
1961
Wolfgang Fahrrad
1961
Die redundante, nicht gewollte Speicherung von Wolfgang und 1961 ist auf
eine schlechte 1NF-Repräsentation zurückzuführen. Wie bereits bekannt, realisieren wir
Person
Name: String
Hobbies: list<String>
Geburtsjahr: Date
durch
Person
Hobby
0..*
0..*
Hobby: String
Name: String
Geburtsjahr: Date
d. h. durch mehrere Tabellen. Deshalb treten mehrwertige Abhängigkeiten
(i. Allg.) nicht auf und müssen nicht weiter berücksichtigt werden ( ô keine 4NFProbleme).
5VF-Probleme sind bei umfangreichen DB-Schemata nur schwer zu erkennen und
werden daher i. Allg. nicht berücksichtigt.
Draft (2. März 2000)
120
Anhang A
Literatur
A.1 Datenbanken
C HEN [1976]
The Entity-Relationship Model: Towards a unified view of Data, In: ACM
Transactions on Database Systems, 1(1), Seiten 9–36
A.2 Objektorientierung
KOWARSCHICK , W. [1994]
Praxis wissensbasierter Systeme, Vorlesungsskript, Universität Augsburg
RUMBAUGH , J., B LAHA , M., P REMERLANI , W., E DDY, F., L ORENSEN , W.
[1991]
Object-Oriented Modeling and Design, Prentice-Hall
RUMBAUGH , J., B LAHA , M., P REMERLANI , W., E DDY, F., L ORENSEN , W.
[1993]
Objektorientiertes Modellieren und Entwerfen, Hanser Verlag, Prentice-Hall
F LANAGAN , D. [1996]
Java in a Nutshell, O’Reilly International Thomson
F LANAGAN , D. [1998]
Java in a Nutshell – Deutsche Ausgabe, O’Reilly International Thomson
H ORSTMANN , C., C ORNELL , G. [1997]
Core Java, Band I – Fundamentals, SUN Microsystems Press, Prentice Hall
H ORSTMANN , C., C ORNELL , G. [1998]
Core Java, Band II – Advanced Features, SUN Microsystems Press, Prentice
Hall
KÖSTLER , G., KOWARSCHICK , W., K IESSLING , W. [1997]
Client-Server Optimization for Multimedia Document Exchange, In: Procee-
121
Draft (2. März 2000)
dings of the Fifth International Conference on Database Systems for Advanced Applications (DASFAA’97), Seiten 135–144, Melbourne, Australia
Draft (2. März 2000)
122
Herunterladen