[[
{ _e: "Personen", pos: [150, 100],
attributes: [
{ _a:"PersNr", options:["primary"], pos: [89, 13] },
{ _a:"Name", pos: [245, 13] },
{ _a:"Adresse", pos: [172, 182],
attributes: [
{ _a: "Straße", pos: [102, 240] },
{ _a: "PLZ", pos: [217, 240] },
{ _a: "Ort", pos: [329, 240] }
] }
]
}
],
[
]]
Personen( PersNr , Name, Adresse_Strasse, Adresse_PLZ, Adresse_Ort )
Wie viele Attribute hat die Tabelle Personen?
https://frage.space
Die einfachste Möglichkeit, Unterattribute im Relationenmodell abzubilden, ist es die Attributshierarchie flachzuklopfen. Da Attribute im Relationenmodell atomare Werte haben, erstellen wir für jedes Sub-Attribut eine eigene Spalte.
Mehrwertiges Attribut → Relation
[[
{ _e: "Personen", pos: [150, 100],
attributes: [
{ _a:"PersNr", options:["primary"], pos: [89, 13] },
{ _a:"Name", pos: [245, 13] },
{ _a:"Telefon", pos: [172, 182], options:["multi"] }
]
}
],
[
]]
Telefonnummern
PersNr Telefon
4 0151-1
4 0151-2
5 0151-3
telefonnummern.persnr ist Fremdschlüssel auf personen.persnr
Ute hat zwei Telefonnummer, Peter nur eine und Anna gar keine.
1:N-Beziehung → Fremdschlüssel
[[
{ _e: "Produkte", pos: [30, 100],
attributes: [
{ _a:"Produktnr", pos: [15, 25], options:["primary"] },
{ _a:"Bezeichnung", pos: [134, 25] },
{ _a:"Preis", pos: [200, 106] }
]
},
{ _e: "Hersteller", pos: [30, 304],
attributes: [
{ _a:"Firma", pos: [200, 280], options:["primary"] },
{ _a:"Land", pos: [200, 345] }
]
}
],
[
{ _r: "sind von",
_e: ["Produkte", "Hersteller"],
card: ["N", "1"] }
]]
produkte.hersteller ist Fremdschlüssel auf hersteller.firma
An die Relation, die im ER-Diagramm an der gegenüberliegenden Seite von der 1 steht, wird ein Fremdschlüssel hinzugefügt. Und zwar hat dieser die gleichen Spaltentypen wie der referenzierte Primärschlüssel. Der Fremdschlüssel-Spaltenname ist hier der Name der referenzierten Tabelle, man kann aber auch den Namen der referenzierten Spalte (Firma) oder den Beziehungsnamen (sind_von) nehmen.
Rekursive Beziehung → Fremdschl.
personen.chef ist Fremdschlüssel auf personen.persnr
Darf eine Person sein eigener Chef sein (also Chef=PersNr)?
Ja sicher
Nee, das geht nicht
https://frage.space
Personen ist nun eine sich selbst referenzierende Tabelle. In der Fremdschlüsselspalte "Chef" ist die ID des Chefs einer Person zu finden. Ute hat keinen Chef, daher ist bei ihr Chef NULL. Es wäre sogar möglich, dort die eigene PersNr einzutragen.
N:M-Beziehung → Relation
17
[[
{ _e: "Kunden", pos: [30, 100],
attributes: [
{ _a:"Kundennr", pos: [12, 30], options:["primary"] },
{ _a:"Name", pos: [124, 23] },
{ _a:"E-Mail", pos: [204, 71]}
]
},
{ _e: "Produkte", pos: [30, 304],
attributes: [
{ _a:"Produktnr", pos: [15, 400], options:["primary"] },
{ _a:"Bezeichnung", pos: [134, 400] },
{ _a:"Preis", pos: [200, 340] }
]
}
],
[
{ _r: "bewerten",
_e: ["Kunden", "Produkte"],
attributes: [ {_a:"Sterne", pos: [150, 175] }, {_a:"Text", pos: [150, 240] } ],
card: ["N", "M"] }
]]
kunden_bewerten_produkte.kundennr ist Fremdschlüssel auf kunden.kundennr
kunden_bewerten_produkte.produktnr ist Fremdschlüssel auf produkte.produktnr
Aus einer N:M-Beziehung wird eine eigene Relation. Diese trägt als Namen z. B. den Beziehungsnamen (bewerten) oder etwas anderes, was verständlich ist (kunden_bewerten_produkte, bewertungen, ...). Die neue Relation besitzt Fremdschlüsselspalten, welche die Primärschlüssel der an der Beziehung teilnehmenden Entities referenzieren. Die Kombination all dieser Fremdschlüsselspalten bilden den Primärschlüssel der Beziehungstabelle. Als weitere Nicht-Schlüssel-Attribute werden die Beziehungsattribute - sofern vorhanden - hinzugefügt.
Schwache Entitätstypen → Relation
[[
{ _e: "Anbieter", pos: [30, 100],
attributes: [
{ _a:"Anbieternr", pos: [15, 25], options:["primary"] },
{ _a:"Anbietername", pos: [134, 25] }
]
},
{ _e: "Handytarif", pos: [30, 304], options: ["weak"],
attributes: [
{ _a:"Tarifbezeichn.", pos: [200, 280], options:["extending_primary"] },
{ _a:"Datenvolumen", pos: [200, 345] },
{ _a:"Preis", pos: [120, 400] }
]
}
],
[
{ _r: "haben", options: ["weak"],
_e: ["Anbieter", "Handytarif"],
card: ["1", "N"] }
]]
Anbieter( Anbieternr , Anbietername )
Handytarife( Anbieternr , Tarifbezeichnung , Datenvolumen, Preis )
handytarife.anbieternr ist Fremdschlüssel auf anbieter.anbieternr
Der schwache Entitätstyp erbt den Primärschlüssel von anderen Entitätstypen. Hier erbt Handytarife den Primärschlüssel von Anbieter, zusätzlich wird er erweitert um die Tarifbezeichnung.
Schwache Entitätstypen → Relation
[[
{ _e: "Kunden", pos: [50, 10],
attributes: [
{ _a:"Kundennr", options:["primary"], pos: [10, 85] },
{ _a:"...", pos: [140, 85] }
]
},
{ _e: "Produkte", pos: [730, 10],
attributes: [
{ _a:"Produktnr", options:["primary"], pos: [690, 85] },
{ _a:"...", pos: [810, 85] }
]
},
{ _e: "Bewertungen", pos: [390, 10], options: ["weak"],
attributes: [
{_a:"Sterne", pos: [340, 100] },
{_a:"Text", pos: [480, 100] } ]
}
],
[
{ _r: "schreiben",
_e: ["Kunden", "Bewertungen"], options: ["weak"],
card: ["1", "N"]
},
{ _r: "für",
_e: ["Bewertungen", "Produkte"], options: ["weak"],
card: ["N", "1"]
}
]]
Kunden(Kundennr , ...)
Produkte(Produktnr , ...)
Bewertungen(Kundennr, Produktnummer , Sterne, Text)
bewertungen.kundennr ist Fremdschlüssel auf kunden.kundennr
bewertungen.produktnr ist Fremdschlüssel auf produkte.produktnr
Dieses Relationenschema ist das gleiche wie...
wenn Bewertungen nicht schwach wäre
bei der N:M-Beziehung "bewertet"
bei einem mehrwertigen Attribut "Bewertung"
bei einer ternären Beziehung "bewertet"
https://frage.space
Der schwache Entitätstyp Bewertungen ist von zwei Entitätstypen existenzabhängig: Kunden und Produkte. Die Bewertungen-Relation hat also als Primärschlüssel die Kombination aus den Primärschlüsseln ebendieser beider Tabellen: Kundennr, Produktnr. Das Resultat ist genau das gleiche wie die Relation, die aus der N:M-Beziehung "bewerten" entstanden ist (siehe 2 Folien zurück).
Ternäre Beziehung → Relation
[[
{ _e: "Kunden", pos: [150, 100],
attributes: [
{ _a:"Kundennr", options:["primary"], pos: [89, 13] },
{ _a:"Name", pos: [245, 13] }
]
},
{ _e: "Tarife", pos: [530, 100],
attributes: [
{ _a:"Bezeichnung", pos: [475, 25], options:["primary"] },
{ _a:"Mindestlaufzeit", pos: [599, 25]},
{ _a:"Preis", pos: [698, 71]}
]
},
{ _e: "Fitnessstudios", pos: [334, 277],
attributes: [
{ _a:"Strasse", pos: [205, 212], options:["primary"] },
{ _a:"Hausnummer", pos: [205, 275], options:["primary"] }
]
}
],
[
{ _r: "buchen",
_e: ["Kunden", "Tarife", "Fitnessstudios"],
card: ["N", "1", "M"],
attributes: [{_a:"Datum", pos: [462, 195]}]
}
]]
Buchung(Kundennr, Studio_Str, Studio_Hausnr , Tarif_Bezeichnung, Datum)
buchung.kundennr ist Fremdschlüssel auf kunden.kundennr
buchung.tarif_bezeichnung ist Fremdschlüssel auf tarife.bezeichnung
buchung(studio_str, studio_hausnr) ist FK auf fitnessstudios(strasse, hausnummer)
Genau wie bei einer binären N:M-Beziehung, wird auch bei einer höhergradigen Beziehung eine separate Relation erstellt. Der Primärschlüssel wird nur aus den Entitätstypen gebildet, an denen keine 1 steht.
Wenn bei Tarife keine 1, sondern ein L stünde...
hätte das keine Auswirkung auf das Relationenschema
müsste man eine weitere Relation erstellen
gehörte Tarif_Bezeichnung zum Primärschlüssel
hä? Kommt nach N, M, nicht O?
https://frage.space
NOT NULL / UNIQUE
⇒ Geburtsort ist NOT NULL
⇒ Geburtsort ist UNIQUE
⇒ Geburtsort ist UNIQUE NOT NULL
Wenn im ER-Diagramm die Krähenfuß-Notation verwendet wird, können die genaueren Kardinalitätsrestriktionen ins Relationenmodell übernommen werden. Im ersten und dritten Diagramm sind Personen in genau einem Ort geboren, d. h. die Geburtsort-Spalte muss NOT NULL sein. NOT NULL heißt, es darf keine NULL-Werte in der Spalte geben. UNIQUE heißt, dass keine doppelten Werte vorkommen dürfen. Das wäre der Fall, wenn in einem Ort nur eine Person geboren sein dürfte.
NOT NULL / UNIQUE
Personen( PersNr , Name, E-Mail, Geburtsort NOT NULL, Kreditkarte UNIQUE )
Personen brauchen einen Geburtsort, daher muss die Spalte NOT NULL sein. Da jede Kreditkarte nur einmal verwendet werden darf, ist die Fremdschlüsselspalte "Kreditkarte" UNIQUE. Der "o" im ER-Diagramm bei Kreditkarten gibt an, dass es Personen ohne Kreditkarte geben darf, daher sind NULL-Werte in der Kreditkarten-Spalte erlaubt.
Generalisierung im Relationenmodell
Mehrere Möglichkeiten der Umsetzung:
Volle Redundanz
Hausklassenmodell
Vertikale Partitionierung
Hierarchierelation
[[
{ _e: "Kunden", pos: [110, 100],
attributes: [
{ _a:"Kundennr", options:["primary"], pos: [15, 10] },
{ _a:"Name", pos: [130, 10] },
{ _a:"E-Mail", pos: [250, 10] }
]
},
{ _e: "Privatkunden", pos: [10, 230], isa: {_e:"Kunden"},
attributes: [ {_a:"Bonuspunke", pos: [35, 310]} ]},
{ _e: "Geschäftskunden", pos: [200, 230], isa: {_e:"Kunden"},
attributes: [ { _a:"USt-IdNr.", pos: [225, 310]} ]},
],
[
]]
Volle Redundanz
Jeder Entitätstyp wird zur eigenständigen Relation (alle Spalten)
Beim Einfügen in Sub-Relationen wird redundante Information in die entsprechenden Super-Relationen eingefügt.
Kunden(Kundennr , Name, E-Mail)
Privatkunden(Kundennr , Name, E-Mail, Bonuspunkte)
Geschäftskunden(Kundennr , Name, E-Mail, USt-ID)
Privatkunden.Kundennr und Geschäftskunden.Kundennr sind Fremdschlüssel auf Kunden.Kundennr.
Durch die Fremdschlüsselbeziehungen wird garantiert, dass die Zeile auch in der Über-Relation existiert.
Volle Redundanz
Peter ist Privatkunde, Anna ist Geschäftskunde und Ute einfach nur Kunde. Beim Einfügen, Ändern und Löschen von Kunden muss sorgfältig darauf geachtet werden, dass diese Operationen konsistent auf allen betreffenden Tabellen erfolgen. Daher ist diese Variante in der Regel nicht empfehlenswert.
Hausklassenmodell
Jeder Entitätstyp wird zur eigenständigen Relation (alle Spalten)
Es wird nur in die speziellste Relation eingefügt.
Kunden(Kundennr , Name, E-Mail)
Privatkunden(Kundennr , Name, E-Mail, Bonuspunkte)
Geschäftskunden(Kundennr , Name, E-Mail, USt-ID)
Hier keine Fremdschlüssel.
Woran erkennt man im Relationenschema den Unterschied zwischen dem Hausklassenmodell und der vollen Redundanz?
Es gibt keinen Unterschied
Weniger Spalten beim Hausklassenmodell
Mehr Spalten beim Hausklassenmodell
Bei der vollen Redundanz gibt es Fremdschlüssel
https://frage.space
Im Hausklassenmodell ist die Suche aufwändig, da diese häufig mehrere Relationen betreffen kann.
Hausklassenmodell
Peter ist Privatkunde, Anna ist Geschäftskunde und Ute einfach nur Kunde. Wollen wir nun alle Kunden finden, muss eine Vereinigung der drei Relationen gebildet werden.
Vertikale Partitionierung
Jeder Entitätstyp wird zur eigenständigen Relation (PK + spezielle Spalten)
Kunden(Kundennr , Name, E-Mail)
Privatkunden(Kundennr , Bonuspunkte)
Geschäftskunden(Kundennr , USt-ID)
Privatkunden.Kundennr und Geschäftskunden.Kundennr sind Fremdschlüssel auf Kunden.Kundennr.
Lediglich die Primärschlüsselwerte sind in dieser Variante redundant. Alles andere wird in den speziellen Relationen gespeichert. Zur Suche sind oft Verbundoperationen nötig, da Daten ein und derselben Entität über mehrere Relationen verteilt (partitioniert) gespeichert werden.
Vertikale Partitionierung
Möchte man hier den Namen und die Umsatzsteuer-ID aller Geschäftskunden wissen, muss man in zwei Tabellen (Kunden und Geschäftskunden) schauen.
Hierarchierelation
Nur eine einzige Relation mit ALLEN Spalten.
Type_Tag gibt den Entitätstypen an
Kunden(Kundennr , Name, E-Mail, Bonuspunkte, USt-ID, Type_Tag)
In dieser Variante ist sowohl Suchen als auch Einfügen besonders einfach. Bei komplexen Generalisierungshierarchien kann es jedoch sehr viele Spalten mit vielen NULL-Werten geben.
Relationale Algebra
18
Die Relationale Algebra besteht aus Operationen, die auf ein oder mehreren Relationen angewendet werden können. Das Ergebnis einer solchen Operation ist wieder eine Relation.
Beispiel: Vereinigung
Der Vereinigungsoperation ⋃ wird auf zwei Relationen angewandt und liefert wieder eine Relation zurück.
RelaX - relational algebra calculator
https://dbis-uibk.github.io/relax/
Gist-ID unseres Webshop-Schemas: d67f16874b528abc6e6c88d07a50b2dc
Mit dem webbasierten Tool RelaX kann man Ausdrücke der relationalen Algebra formulieren und ausführen. Oben links im Tool wähnt man aus verschiedenen Beispielschemas, man kann auch ein eigenes Schema erstellen oder ein vorgefertigtes mittels einer Gist-ID importieren. Die Gist-ID des Webshop-Beispiels aus dieser Vorlesung steht auf dieser Folie und kann zum Üben von Anfragen auf diesem Schema verwendet werden.
Mengenoperationen
19
Relationen sind Mengen von Tupeln
Mengen können vereinigt, geschnitten und voneinander subtrahiert werden
Das geht aber nur, wenn die Mengen vereinigungsverträglich sind
Vereinigungsverträglichkeit
Gleiche Anzahl von Spalten
Kompatible Datentypen
⋂ Schnittmenge
19
Diejenigen Zeilen, die in beiden Relationen vorkommen.
Die Zeile muss exakt gleich aussehen, sodass sie im Ergebnis zu sehen ist. Die Operation ⋂ würde nicht funktionieren, wenn die beiden Tabellen eine unterschiedliche Anzahl an Spalten haben. Auch, wenn Datentypen nicht kompatibel wären (z. B. erste Spalte keine Zahl sondern ein Datum), sind die Mengen nicht vereinigungsverträglich und daher kann auch keine Schnittmenge gebildet werden. Auf Englisch heißt die Schnittmenge Intersection.
\ Mengensubtraktion
19
Die Zeilen der ersten ohne die der zweiten Relation.
Der Minus-Operator \ ist anders als die Vereinigung und Schnittmenge nicht symmetrisch. Die Zeilen der zweiten Relation werden von denen der ersten abgezogen. Im gezeigten Beispiel werden von {Ute, Peter} die Personen {Peter, Anna} abgezogen. Wenn man etwas abzieht, was nicht in der Menge ist (Anna), passiert nichts. Aber Peter wird abgezogen, sodass im Ergebnis lediglich Ute ist.
⋃ Vereinigung
20
Alle Zeilen aus beiden Relationen.
Relationen sind Mengen von Tupeln und in Mengen gibt es keine Duplikate. Daher erscheint hier im Ergebnis der Kunde Peter nur einmal, obwohl er in beiden Relationen jeweils einmal vorkommt. Auf Englisch heißt Vereinigung Union.
π Projektion
21
$\pi_{A_1, A_2, \dots, A_n}(R)$
Beschränkung der Relation $R$ auf die Spalten $A_1, A_2, \dots, A_n$
$\pi_{kundennr, name}(Kunden)$
Wie viele Zeilen kommen bei einer Projektion auf einer nicht leeren Relation R heraus?
Genau |R|
Zwischen 0 und |R|
Zwischen 1 und |R|
Zwischen |R| und ∞
https://frage.space
Die Projektion ist ein unärer Operator, das heißt er nimmt nur eine Relation als Eingabe (Vereinigung etc. sind binär). Das Ergebnis ist gleich der Eingaberelation, jedoch nur mit den spezifizierten Spalten. Im Beispiel interessieren wir uns nur für die Kundennummern und Namen von Kunden, nicht für weitere Attribute.
π Projektion
Achtung: Duplikateliminierung!
$\pi_{hersteller}(Produkte)$
Relationen sind Mengen von Tupeln und Mengen beinhalten keine Duplikate. Daher kann es vorkommen, dass das Ergebnis einer Projektion weniger Zeilen als die Eingaberelation hat.
σ Selektion
22
$\sigma_{P}(R)$
Auswahl derjenigen Zeilen der Relation $R$, die das Kriterium $P$ erfüllen.
$\sigma_{hersteller='Monsterfood'}(Produkte)$
Selektion
$\sigma_{preis>1}(\sigma_{hersteller='Monsterfood'}(Produkte))$
Klammern weglassen:
$\sigma_{preis>1}\sigma_{hersteller='Monsterfood'}(Produkte)$
Selektionen mit AND verbinden:
$\sigma_{preis>1 \wedge hersteller='Monsterfood'}(Produkte)$
OR geht so:
$\sigma_{preis>1 \vee hersteller='Monsterfood'}(Produkte)$
Das entspricht:
$\sigma_{preis>1}(Produkte) \cup \sigma_{hersteller='Monsterfood'}(Produkte)$
Welche Produkte vom Hersteller Monsterfood kosten mehr als 1 EUR? Die unteren beiden Ausdrücke liefern Produkte, die von Monsterfood sind oder mehr als einen Euro kosten (oder beides ist der Fall).
Operatorabfolgen
"Von welchen Herstellern aus Österreich gibt es keine Produkte?"
Welche Hersteller sind aus Österreich? $\sigma_{land='Österreich'}(Hersteller)$
Wie heißen diese Hersteller? $\pi_{firma}\sigma_{land='Österreich'}(Hersteller)$
Vor welchen Herstellern sind unsere Produkte? $\pi_{hersteller}(Produkte)$
Subtraktion von 2. und 3.: $\pi_{firma}\sigma_{land='Österreich'}(Hersteller) \setminus \pi_{hersteller}(Produkte)$
Operatorbäume
Ein Operatorbaum stellt ein Ausdruck der relationalen Algebra in Baum-Form dar. Die Wurzel (ganz oben) liefert das Ergebnis, in den Blättern (ganz unten) befinden sich die verwendeten Relationen. Dazwischen bilden unäre und binäre Operationen die Knoten des Baumes.
⨯ Kartesisches Produkt
25
"Jedes mit jedem"
$Produkte \times Bewertungen$
Das kartesische Produkt aus zwei Relationen hat alle Attribute beider Relationen und besteht aus jedem Tupel der einen verknüpft mit jedem Tupel der anderen Relation.
Tabellenprefix
Der Name der Relation kann bei Attributen als Prefix angegeben werden.
$\sigma_{Produkte.Produktnr=Bewertungen.Produktnr}(Produkte \times Bewertungen)$
In dieser Anfrage werden alle Produkte mit allen Bewertungen verbunden und im Anschluss eine Selektion darüber gemacht, sodass die Produktnummer des Produktes und der Bewertung übereinstimmt. Alles andere wären unsinnige Zeilen (Bewertung eines anderen Produkts). Da das Attribut Produktnr in beiden Relationen vorkommen, verwenden wir den Relationennamen als Prefix, z. B. produkte.produktnr, um die Attribute voneinander zu unterscheiden
ρ Umbenennungsoperator
Relation umbenennen
$\rho_{P1}(Produkte)$
Attribut umbenennen
$\rho_{bez\leftarrow bezeichnung}(Produkte)$
Welche Produkte kosten mehr als die Spülmaschinentabs?
Spätestens wenn man ein und dieselbe Relation mehrfach innerhalb einer Anfrage braucht, ist es hilfreich Relationen oder Attribute einen Alias zu geben.
⋈ Join (Verbund)
24
Ein Join ist ein Kreuzprodukt mit anschließender Selektion, welche die Spaltenwerte der beiden Relationen vergleicht
Gleichverbund (Equi-Join)
$R \bowtie_{P}S = \sigma_{P}(R \times S)$
Welche Produkte sind von einem Hersteller aus den USA?
$\pi_{Bezeichnung}\sigma_{Land='USA'}(Produkte \bowtie_{Produkte.Hersteller=Hersteller.Firma}Hersteller)$
Es gilt: $R ⋈ S = S ⋈ R$
$R \bowtie_{P}S$ bedeutet, dass die beiden Relationen R und S anhand des Join-Prädikats P verbunden werden.
Suche nach Join-Partnern
$Produkte \bowtie_{Produkte.Hersteller=Hersteller.Firma}Hersteller$
Man kann sich die Ausführung eines Joins auch so vorstellen, dass eine Relation von oben nach unten durchscannt wird - z. B. hier die Produkttabelle - und für jede Zeile ein (oder kein oder mehrere) Join-Partner in der anderen Relation - hier: Hersteller - gesucht wird. Die Attributwerte der gefundenen Zeile wird an die Ergebniszeile drangehangen. Wird kein Join-Partner gefunden - hier beim Katzenfutter der Fall -, taucht die Zeile nicht im Ergebnis auf. Würde eine Zeile mehrere Joinpartner finden, taucht sie mehrfach im Ergebnis auf. Jeweils einmal mit dem entsprechenden Join-Partner.
Ergebnis des Joins
$Produkte \bowtie_{Produkte.Hersteller=Hersteller.Firma}Hersteller$
Der Join ist verlustbehaftet.
Was ist verloren gegangen?
Produkte mit Hersteller NULL
Hersteller, von denen es keine Produkte gibt
beides
gar nichts
https://frage.space
Die Ergebnisrelation des Joins zwischen zwei Relationen besitzt alle Spalten beider Relationen. Zu jeder Zeile der beiden Relationen existieren entsprechend viele Zeilen im Ergebnis, je nachdem wie viele Join-Partner zu ihr gefunden werden. Der Hersteller Monsterfood hat sogar zwei Join-Partner gefunden, daher taucht die Hersteller-Zeile (Monsterfood, USA) im Ergebnis zweimal auf. Das Produkt Katzenfutter hat hier keinen Join-Partner gefunden, der Hersteller Holzkopf ebenfalls nicht. Da also beim Join etwas verloren gegangen ist (Katzenfutter und Hersteller Holzkopf), nennt man den Join verlustbehaftet.
Verlustfreier Join
$Produkte \bowtie_{Produkte.Hersteller=Hersteller.Firma}Hersteller$
Hier taucht jedes Tupel aus beiden Relationen im Join-Ergebnis auf. Der Join ist verlustfrei.
Rekonstruktion der Tabellen
$produkte = \pi_{produktnr, bezeichnung, preis, hersteller}(V)$
$hersteller = \pi_{firma, land}(V)$
Aus dem Join-Ergebnis V lassen sich die beiden ursprünglichen Relationen wieder mittels Projektionen rekonstruieren. Das funktioniert allerdings nur, wenn der Verbund verlustfrei ist.
Äußerer Verbund
$\bowtie$ Innerer Verbund
Nur die Zeilen, die Join-Partner finden, sind im Ergebnis
$⟕$ Linker äußerer Verbund
Alle Zeilen der linken Relation sind definitiv im Ergebnis
$⟖$ Rechter äußerer Verbund
Alle Zeilen der rechten Relation sind definitiv im Ergebnis
$⟗$ Voller äußerer Verbund
Alle Zeilen beider Relation sind definitiv im Ergebnis
$⟕$ Linker äußerer Verbund
27
$Produkte ⟕_{Produkte.Hersteller=Hersteller.Firma}Hersteller$
Alle Zeilen der links vom Left-Join-Operator stehenden Relation erscheinen auf jeden Fall im Ergebnis. Wenn sie keinen Join-Partner in der rechten Tabelle finden - das ist hier beim Katzenfutter der Fall -, bleiben die Attribute der rechten Tabelle alle NULL.
$⟖$ Rechter äußerer Verbund
28
$Produkte ⟖_{Produkte.Hersteller=Hersteller.Firma}Hersteller$
Es gilt: $R ⟖ S = S ⟕ R$
Beim right outer Join sind zusätzlich zu den normalen Join-Ergebniszeilen diejenigen Zeilen der rechten Tabelle im Ergebnis wiederzufinden, die keinen Join-Partner in der linken Tabelle finden. Auch hier werden die Spalten der linken Tabelle mit NULL-Werten belegt.
$⟗$ Voller äußerer Verbund
29
$Produkte ⟗_{Produkte.Hersteller=Hersteller.Firma}Hersteller$
Es gilt: $R ⟗ S = S ⟗ R$
Jede Zeile der linken Relation und jede Zeile der rechten Relation tauchen stets im Ergebnis des full outer Joins auf. Der volle äußere Verbund ist damit immer verlustfrei.
Join-Varianten
Innerer / linker / rechter / voller äußerer Join
$R \bowtie_{P} S$ $R ⟕_{P} S$ $R ⟖_{P} S$ $R ⟗_{P} S$
Gleichverbund (Equi-Join)
$R \bowtie_{R.a = S.x \wedge R.b = S.y \wedge \dots} S$
Theta-Join
$R \bowtie_{R.a \theta S.x \wedge \dots} S$ mit $\theta \in \{<,≤,=,≠,≥,>\}$
Beispiele: Equi-/Theta-Joins
Finde zu jedem Produkt seinen Hersteller:
$produkte \bowtie_{Produkte.Hersteller=Hersteller.Firma}hersteller$
Finde zu jedem Produkt teurere Produkte als es selbst:
$\rho_{P1}(produkte) \bowtie_{P1.preis < P2.preis} \rho_{P2}(produkte)$
Join-Varianten
Natürlicher Verbund (natural Join)
$R \bowtie S$ Gleichverbund über die gleich heißenden Attribute. Im Ergebnis sind solche Attribute nur einmal vorhanden.
Self-Join
$R \bowtie_P R$
Semi-Join
$R \ltimes_P S = \pi_{R.*}(R \bowtie_P S)$
Welcher Join-Bedingung entspricht ein natürlicher Verbund zwischen A(x,y,z) und B(s,t,x,y)?
A.x = B.s
A.x = B.x
A.y = B.y
A.x = B.x ∧ A.y = B.y
https://frage.space
Beispiel: Natürlicher Verbund
$produkte \bowtie bewertungen$
Entspricht: $\pi_{produkte.produktnummer, bezeichnung, preis, hersteller, kundennr, sterne, bewertungstext}$ $(produkte \bowtie_{produkte.produktnr = bewertungen.produktnr} bewertungen)$
In den Relationen Produkte und Bewertungen gibt es ein gemeinsames Attribut, die Produktnummer. Daher ist der natürliche Verbund ein Gleichverbund über die Produktnummer. Diese Spalte taucht im Ergebnis dann aber nur einmal auf.
Beispiel: Self-Join
$\rho_{K1}(personen) \bowtie_{K1.chef = K2.persnr} \rho_{K2}(personen)$
Wir joinen die Personentabelle mit sich selbst anhand der Fremdschlüsselbeziehung zwischen Chef und Kundennr. Im Ergebnis sehen wir zu jeder Person, die einen Chef hat, die Details zur Person und zum jeweiligen Chef. Würden wir den Join ⋈ durch einen Left-Join ⟕ ersetzen, so erschienen auch Personen ohne Chef im Ergebnis. Dann mit NULL-Werten in den hinteren drei Spalten.
Beispiel: Semi-Join
$produkte \ltimes_{produkte.produktnr=bewertungen.produktnr} bewertungen $
Alle Produkte, die schon einmal bewertet wurden.
Der Semi-Join unterscheidet sich vom inneren Verbund dadurch, dass im Ergebnis nur die Spalten der linken Relation zu sehen ist. Der Semi-Join hat also die gleichen Attribute wie die linke Relation, aber nur diejenigen Zeilen, die einen Join-Partner in der rechten Relation finden würden. Im Beispiel hier interessiert man sich also nicht dafür, wer ein Produkt wie bewertet hat, sondern lediglich dass es bewertet wurde. Verwendet wurde hier der linke Semi-Join ⋉. Beim rechten Semi-Join ⋊ wird sich auf die Attribute der rechten Relation beschränkt.
÷ Division
$R \div S$
Diejenigen Tupel aus R (ohne die Spalten von S), die in jeder Kombination mit allen Tupeln aus S vorkommen.
Es gilt: $(R \times S) \div S = R$
Die Division ist hilfreich bei Fragen der Art "Wer hat alle..." oder "Wer hat jedes...". Der Operator kann auch mit den bisher vorgestellten Operationen dargestellt werden: $R \div S = \pi_{R.* \setminus S.*}(R) \setminus \pi_{R.* \setminus S.*}((\pi_{R.* \setminus S.*}(R)\times S) \setminus R)$ (Formel nicht klausurrelevant)
Beispiel: Division
Welche Kunden haben alle Produkte bewertet?
$\pi_{kundennr, produktnr}(bewertungen)$
$\pi_{produktnr}(produkte)$
$\pi_{kundennr, produktnr}(bewertungen) \div \pi_{kundennr}(kunden)$
Hier gehen wir der Einfachheit halber davon aus, dass es nur die beiden Produkte 17 und 29 gibt. Die Division liefert diejenigen Kunden, die alle diese Produkte bewertet hat.
Anfrageoptimierung
"Wie heißen die Produkte, die Kunde Nr. 5 bewertet hat?"
Äquivalente Ausdrücke:
$\pi_{bezeichnung}\sigma_{kundennr=5}\sigma_{produkte.produktnr=bewertungen.produktnr}(produkte\times bewertungen)$
$\pi_{bezeichnung}(\pi_{produktnr, bezeichnung} produkte\bowtie \pi_{produktnr}\sigma_{kundennr=5}(bewertungen))$
$\pi_{bezeichnung}\sigma_{kundennr=5}(produkte\bowtie bewertungen)$
$\pi_{bezeichnung}(produkte\bowtie \sigma_{kundennr=5}(bewertungen))$
Welcher Ausführungsplan ist besser / "billiger"?
Welcher Plan ist der beste?
https://frage.space
Anfrageoptimierung
Überführung eines Ausdrucks in einen äquivalenten möglichst effizient auszuführenden Ausdruck.
Kostenbasierte Optimierer
Jeder Ausführungsplan erhält Kostenschätzung. Der Plan mit den geringsten Kosten wird gewählt.
Beispiel: Kosten = Größe der Zwischenergebnisse
100.000 Kunden, 500.000 Bewertungen. Schätzen Sie: |σ kundennr=5 (bewertungen)|
https://frage.space
Beispiel: Anfrageoptimierung
Annahme: 100.000 Kunden, 500.000 Bewertungen, 300.000 Produkte
Der rechte Plan ist billiger, da die Zwischenergebnisse deutlich kleiner sind: 300.000+300.000+500.000+5+5+5+5=1.100.020; links: 150.001.300.010; Auch haben die Zwischenergebnisse weniger Spalten.
Heuristiken
Frühstmögliche Selektion
Join statt Kreuzprodukt
Frühstmögliche Projektion (ohne Duplikateliminierung)
Join-Reihenfolge so wählen, dass Zwischenergebnisse klein sind
Folgen von Selektionen und Projektionen zusammenfassen
Selektionen statt Mengenoperationen
Nichts doppelt berechnen
Heuristiken
Frühstmögliche Selektion
Vorher: $\sigma_{kundennr=5}(produkte \bowtie bewertungen)$
Nachher: $produkte \bowtie \sigma_{kundennr=5}(bewertungen)$
Join statt Kreuzprodukt
Vorher: $\sigma_{produkte.produktnr=bewertungen.produktnr}(produkte \times bewertungen)$
Nachher: $produkte \bowtie_{produkte.produktnr=bewertungen.produktnr} (bewertungen)$
Frühstmögliche Projektion (ohne Duplikateliminierung)
Vorher: $\pi_{bezeichnung}(produkte \bowtie bewertungen)$
Nachher: $\pi_{bezeichnung}(\pi_{produktnr, bezeichnung}(produkte) \bowtie bewertungen)$
Warum haben wir nach der Optimierung zwei Projektionsoperationen in der Anfrage?
Wegen der Sicherheit
Wegen der Redundanz
Wegen der Einfachheit
Wegen des Joins
https://frage.space
Bei der frühestmöglichen Projektion ist darauf zu achten, dass keine Spalten frühzeitig eliminiert werden, die noch für Joins, Selektionen, etc. benötigt werden. Außerdem darf bei der Projektion noch keine Duplikateliminierung erfolgen, da sonst das Ergebnis evtl. nicht mehr äquivalent ist.
Heuristiken
Join-Reihenfolge so wählen, dass Zwischenergebnisse klein sind
Vorher: $(kunden \bowtie bewertungen) \bowtie \sigma_{hersteller='Monsterfood'}(produkte)$
Nachher: $(bewertungen \bowtie \sigma_{hersteller='Monsterfood'}(produkte)) \bowtie kunden$
Folgen von Sel. und Proj. zusammenfassen
Vorher: $\pi_{bezeichnung}\pi_{produktnr,bezeichnung}\sigma_{preis \le 5}\sigma_{hersteller='Monsterfood'}produkte$
Nachher: $\pi_{bezeichnung}\sigma_{preis \le 5 \wedge hersteller='Monsterfood'}produkte$
Selektionen statt Mengenoperationen
Vorher: $\sigma_{hersteller='Monsterfood'}(produkte) \cup \sigma_{hersteller='Calgonte'}(produkte)$
Nachher: $\sigma_{hersteller='Monsterfood' \vee hersteller='Calgonte'}(produkte)$
Bei der frühestmöglichen Projektion ist darauf zu achten, dass keine Spalten frühzeitig eliminiert werden, die noch für Joins, Selektionen, etc. benötigt werden. Außerdem darf bei der Projektion noch keine Duplikateliminierung erfolgen, da sonst das Ergebnis evtl. nicht mehr äquivalent ist.
Kardinalitätsschätzung
Wie viele Tupel sind im Ergebnis einer Operation zu erwarten?
Hilfreiche Statistiken:
Kardinalitäten der Tabellen (Anzahl Zeilen)
Kardinalitäten der Spalten (Anzahl distinkter Werte)
Kleinster, größter Wert je Spalte, Median, ...
Werte-Histogramme (Häufigkeitsverteilung)
Erfahrungen über Verschätzungen in der Vergangenheit (→ lernende Optimierer)
...
Kardinalitätsschätzung: Selektion
Annahme: Gleichverteilung
|R| (Anzahl Zeilen in R)
|R.a| (Anzahl distinkter Werte in Spalte R.a)
$|\sigma_{R.a = x}(R)| = \frac{|R|}{|R.a|}$
Beispiel:
$|\sigma_{geschlecht='weiblich'}(Personen)| = \frac{1}{3} |Personen|$
Wird nach einem bestimmten Wert in einer Spalte gesucht und liegen keine weiteren Informationen über Werteverteilungen innerhalb dieser Spalte vor, wird von Gleichverteilung ausgegangen. Im Beispiel auf dieser Folie wird geschätzt, dass ein Drittel aller gespeicherten Personen weiblich sind, weil es drei verschiedene Werte in der Spalte Geschlecht gibt (männlich, weiblich, divers).
Kardinalitätsschätzung: Selektion
Selektivitätsfaktor $sf_P$: $|\sigma_P R|=sf_P \cdot |R|$
Annahme: Werteunabhängigkeit
$sf_{P \wedge Q} = sf_P \cdot sf_Q$
Beispiel:
3 verschiedene Geschlechter, 1000 verschiedene Vornamen
$|\sigma_{geschlecht='weiblich' \wedge vorname='Peter'}(Personen)|$ $ = \frac{1}{3} \cdot \frac{1}{1000} |Personen|$
Was kommt raus?
1/3 Personen
1/1000 Personen
1/1003 Personen
1/3000 Personen
https://frage.space
$|\sigma_{geschlecht='männlich' \wedge vorname='Peter'}(Personen)| = \frac{1}{3} \cdot \frac{1}{1000} |Personen|$
Da in der Regel die Information nicht vorliegt, dass zwischen bestimmten Spalten eine Werteabhängigkeit besteht, wird von Unabhängigkeit ausgegangen. Wahrscheinlich wird in Wirklichkeit keine Frau in der Personentabelle Peter heißen. In der unteren Anfrage filtert das Geschlechts-Kriterium wahrscheinlich nichts aus.
Kardinalitätsschätzung: ⨯
$|R \times S| = |R| \cdot |S|$
Beispiel: $|kunden \times kunden| = |kunden|^2$
Kardinalitätsschätzung: ⋈
$|R \bowtie_{R.a=S.a} S|$
Im Allgemeinen: $0 \le |R \bowtie_{R.a=S.a} S| \le |R| \cdot |S|$
Wenn R.a Fremdschlüssel auf S.a ist: $|R \bowtie_{R.a=S.a} S = |R|$
Beispiel: |$produkte \bowtie bewertungen| = |bewertungen|$
Haben die Tabellen R und S völlig verschiedene Werte in der Spalte a, ist das Ergebnis des Joins leer. Wenn die Join-Spalten eine Fremdschlüssel-Primärschlüssel-Beziehung darstellen, hat das Ergebnis des Joins so viele Zeilen, wie die Tabelle mit der Fremdschlüsselspalte (abzgl. der Anzahl von NULL-Werten in dieser), da jede solche Zeile genau einen Join-Partner in der anderen Tabelle findet, unabhängig davon, wie groß diese andere Tabelle ist. Gibt es beispielsweise nur ein Produkt, sind alle Bewertungen über dieses eine Produkt. Gibt es deutlich mehr Produkte als Bewertungen, sind einige Produkte nicht bewertet worden. Im Join-Resultat sind in jedem Fall genau so viele Zeilen wie in der Bewertungs-Tabelle. Die Produktnr-Spalte ist dort nie NULL.
Normalformenlehre
30
Was ist ein gutes DB-Schema?
Funktionale Abhängigkeiten
Superschlüssel, Schlüsselkandidaten
Normalformen: 1NF, 2NF, 3NF
Ist dies ein gutes DB-Schema?
cd_id
tracknr
album
band
land
song
101 1 Jupiter Eddy G. DE All ducks
101 2 Jupiter Eddy G. DE Far away
202 1 Mars Eddy G. DE Meersalz
202 2 Mars Eddy G. DE Mehr Salz
303 1 Stone Bob 88 EN I'm 88
Was ist an diesem Schema nicht so gut?
Inkonsistenz
Redundanz
Unverständlich
Falscher Primärschlüssel
https://frage.space
Dieses Datenbankschema ist eher schlechter Natur. Es herrschen viele Redundanzen. Dinge, die in unterschiedliche Relationen gehören, wurden in eine Relation zusammengeworfen.
Anomalien bei Redundanzen
cd_id
tracknr
album
band
land
song
Einfügeanomalie
Wir können keine neue Band hinzufügen, wenn sie noch kein Album herausgebracht hat.
Änderungsanomalie
Wenn wir das Land einer Band ändern, muss diese Änderung an vielen Stellen erfolgen.
Löschanomalie
Wenn wir das letzte Album einer Band löschen, verlieren wir die Band-Infos.
Funktionale Abhängigkeit
$A$ und $B$ sind Attributmengen aus der Relation $R$
$A \rightarrow B$ (lies: A bestimmt B)
Immer wenn zwei Zeilen in $R$ die gleichen Werte in den $A$-Attributen haben, dann sind auch die Werte in den $B$-Attributen gleich.
Beispiel: $band \rightarrow land$
Immer wenn zwei Zeilen in unserer CD-Track-Tabelle in der Spalte "band" das gleiche stehen haben, so muss auch der Wert in "land" gleich sein. Bei der Band Eddy G. ist das Land immer DE.
Funktionale Abhängigkeiten ergeben sich aus der Semantik der Anwendung. Sie herrschen in einem DB-Schema. Man kann sie nicht von den aktuell gespeicherten Daten ableiten. Funktionale Abhängigkeiten sind Bedingungen, die in jedem DB-Zustand stets gelten.
Funktionale Abhängigkeiten
Es gilt: $cd\_id \rightarrow album; cd\_id \rightarrow band; band \rightarrow land;$
$cd\_id, tracknr \rightarrow song$
Welche funktionalen Abhängigkeiten gilt hier NICHT?
cd_id, tracknr → cd_id
cd_id, tracknr → album, tracknr
cd_id → land
song → tracknr
https://frage.space
Volle funktionale Abhängigkeit
$A \Rightarrow B$ (lies: A bestimmt B voll-funktional)
Dies ist der Fall wenn
$A \rightarrow B$ und
$\not \exists X \subset A: X \rightarrow B$
Beispiel: $cd\_id, tracknr \rightarrow land$
Aber nicht: $cd\_id, tracknr \Rightarrow land$, weil bereits $cd\_id \rightarrow land$
Superschlüssel
Die Attributmenge $A$ ist Superschlüssel der Relation R, genau dann wenn $A \rightarrow R$ (sie bestimmt alle Attribute)
Ist cd_id Superschlüssel?
$cd\_id \rightarrow album; cd\_id \rightarrow band; band \rightarrow land;$
$\Rightarrow cd\_id \rightarrow cd\_id, album, band, land$
$\Rightarrow cd\_id$ ist kein Superschlüssel (z. B. $cd\_id \not\rightarrow tracknr$)
Ist cd_id, tracknr Superschlüssel?
$cd\_id \rightarrow album; cd\_id \rightarrow band; band \rightarrow land; cd\_id, tracknr \rightarrow song$
$\Rightarrow cd\_id, tracknr \rightarrow cd\_id, tracknr, album, band, land, song = R$
$\Rightarrow cd\_id, tracknr$ ist Superschlüssel
Schlüsselkandidat
Die Attributmenge $A$ ist Schlüsselkandidat von R, wenn
$A$ Superschlüssel ist und
keine echte Teilmenge von $A$ Superschlüssel ist.
Ein Schlüsselkandidat ist ein minimaler Superschlüssel.
Ist cd_id, tracknr Schlüsselkandidat?
cd_id, tracknr ist Superschlüssel (siehe vorherige Folie)
cd_id ist kein Superschlüssel (siehe vorherige Folie)
tracknr ist kein Superschlüssel (nur $tracknr \rightarrow tracknr$)
$\Rightarrow cd\_id, tracknr$ ist Schlüsselkandidat
{cd_id, tracknr, song} ist ein...
Superschlüssel
Schlüsselkandidat
beides
weder noch
https://frage.space
Ein Schlüsselkandidat eignet sich dafür, als Primärschlüssel der Relation eingesetzt zu werden. Wenn es mehrere Schlüsselkandidaten gibt, wählt man einen davon aus, der Primärschlüssel wird.
1. Normalform (1NF)
31
Eine Relation ist in erster Normalform, wenn alle ihre Attribute weder zusammengesetzt noch mengenwertig noch relationenwertig sind.
=> Ist hier der Fall! Die Relation ist in 1NF.
(NF)2 = Non First Normal Form
pizza_id bezeichnung zutaten preis
1 Spezial Salami, Schinken, Pilze
größe preis
klein 7.00 groß 8.50
2 Hawaii Ananas, Schinken
größe preis
klein 6.50 groß 7.50
Zutaten ist ein mengenwertiges Attribut, Preis ist ein relationenwertiges Attribut.
=> Nicht in 1NF.
Überführung in 1NF
Attribute flachklopfen.
pizza_id bezeichnung zutat
1 Spezial Salami
1 Spezial Schinken
1 Spezial Pilze
... ... ...
pizza_id bezeichnung größe preis
1 Spezial klein 7.00
1 Spezial groß 8.50
... ... ... ...
Jetzt ist das Schema in 1NF.
Welche volle funktionale Abhängigkeit gilt in der obigen Tabelle?
pizza_id ⇒ bezeichnung
pizza_id, zutat ⇒ bezeichnung
zutat ⇒ bezeichnung
pizza_id, bezeichnung ⇒ zutat
https://frage.space
2. Normalform (2NF)
Eine Relation ist in zweiter Normalform, wenn sie in 1NF ist und jedes Nicht-Schlüsselattribut voll vom ganzen Schlüssel abhängt.
Ist Pizza1(pizza_id , bezeichnung, zutat ) in 2NF?
Überprüfe für Nicht-Schlüsselattribut "bezeichnung": $pizza\_id, zutat \Rightarrow bezeichnung$ ?
Nicht der Fall, weil bereits $pizza\_id \rightarrow bezeichnung$
Damit ist die Relation nicht in 2NF.
Überführung in 2NF
Zerlegung in Relationen, die den Teil der Schlüsselattribute besitzen, von dem die jeweiligen Nicht-Schlüssel-Attribute voll funktional abhängen.
Gegeben: Pizza1(pizza_id , bezeichnung, zutat )
$pizza\_id \rightarrow bezeichnung$
Resultat in 2NF: Pizza1a(pizza_id , zutat ) und Pizza1b(pizza_id , bezeichnung)
Wichtig bei Zerlegungen: Zerlegung muss verlustfrei erfolgen und ein Join der neuen Tabellen muss wieder die ursprüngliche Tabelle ergeben.
CD-Track-Beispieltabelle
cd_id
tracknr
album
band
land
song
$cd\_id \rightarrow album; cd\_id \rightarrow band; band \rightarrow land; cd\_id, tracknr \rightarrow song$
Ist die Tabelle in 2NF?
Ist die Tabelle in 2NF?
Ja, weil z. B. {cd_id, tracknr} ⇒ album
Nein, weil cd_id → tracknr
Nein, weil cd_id → album
Nein, weil tracknr → album
https://frage.space
Überprüfe für Nicht-Schlüsselattribut "album", ob $cd\_id, tracknr \Rightarrow album$ ?
Nein, weil $cd\_id \rightarrow album$ ⇒ Die Relation ist also nicht in 2NF
Überführung in 2NF:
Tracks(cd_id ,tracknr , song)
Alben(cd_id , album, band, land)
Bei der Überführung der CD-Track-Tabelle in 2NF wurde diese Tabelle in zwei Tabellen zerlegt. Wir geben ihnen sinnvolle Namen: Alben und Tracks. Lediglich die Spalte "song" ist vom ganzen Schlüssel voll funktional abhängig. Die anderen Nicht-Schlüsselattribute hängen nur von der CD_ID ab und werden daher in die neue Alben-Relation ausgelagert.
3. Normalform (3NF)
Eine Relation ist in dritter Normalform, wenn sie in 2NF ist und es keine nicht-trivialen transitiven Abhängigkeiten zwischen Nicht-Schlüsselattributen gibt.
Triviale Abhängigkeit: $A \rightarrow X$ mit $X \subseteq A$
Transitive Abhängigkeit: $A \rightarrow B; B \rightarrow C$
Ist Alben(cd_id , album, band, land) in 3NF?
Ist Alben(cd_id , album, band, land) in 3NF?
Ja, weil es keine transitiven Abhängigkeiten gibt
Nein, weil cd_id → band; band → land
Nein, weil cd_id, band → cd_id; cd_id → band
Ich weiß es nicht! Ich weiß es einfach nicht!!!
https://frage.space
Nein, weil es folgende transitive Abhängigkeit gibt: $cd\_id \rightarrow band; band \rightarrow land$
Ein Nicht-Schlüssel-Attribut (das sind Attribute, die zu keinem Schlüsselkandidaten gehören) darf keine anderen Nicht-Schlüssel-Attribute funktional bestimmen. Ist dies der Fall, ist die Relation in 3NF.
Überführung in 3NF
Transitive Abhängigkeit: $A \rightarrow B; B \rightarrow C$
Entfernen von C aus der Relation
Neue Relation hat Attribute B (Primärschlüssel) und C
Gegeben: Alben(cd_id , album, band, land)
$cd\_id \rightarrow band; band \rightarrow land$
Resultat in 3NF:
Alben(cd_id , album, band)
Bands(band , land)
Kapitelzusammenfassung
Relation/Tabelle = Menge von Tupeln
Primärschlüssel, Fremdschlüssel, NULL-Werte
Überführung ER → Relationenschema
Relationale Algebra: $\pi, \sigma, \bowtie, \times, \cup, \div, \dots$
Join: Inner, Left/Right/Full Outer, ...
Anfrageoptimierung / Heuristiken
Funktionale Abhängigkeiten
Superschlüssel, Schlüsselkandidaten
Normalformen: 1NF, 2NF, 3NF