Relationale Algebra: Unterschied zwischen den Versionen
Kowa (Diskussion | Beiträge) Die Seite wurde neu angelegt: „{{In Bearbeitung}} {{Qualität |correctness = 0 |extent = 0 |numberOfReferences = 0 |qualityOfReferences = 0 |conformance = 0 }} …“ |
Kowa (Diskussion | Beiträge) |
||
(186 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
{{Qualität | {{Qualität | ||
|correctness = | |correctness = 2 | ||
|extent = | |extent = 2 | ||
|numberOfReferences = | |numberOfReferences = 3 | ||
|qualityOfReferences = | |qualityOfReferences = 5 | ||
|conformance = | |conformance = 5 | ||
}} | }} | ||
= | In der Theorie der [[Datenbank]]en versteht man unter einer '''relationalen Algebra''' oder '''Relationenalgebra''' eine Menge von Operationen zur Manipulation von [[Relation|Relationen]]. Sie ermöglicht es, Relationen zu filtern, zu verknüpfen, zu aggregieren oder anderweitig zu modifizieren, um Anfragen an eine Datenbank zu formulieren.<ref name="Ullman_Vol_I_S_53">{{Quelle|Ullman (1988)}}, Seite=53</ref><ref name="Elmasri_Navate_Kapitel_S_242">{{Quelle|Elmasri, Navathe (2002)}}, Seite 242</ref> | ||
Normalerweise werden Anfragen und Programme nicht direkt in einer relationalen Algebra formuliert, sondern in einer deklarativen Sprache wie [[SQL]],<ref name="Ullman_Vol_I_S_210">{{Quelle|Ullman (1988)}}, Seite=210</ref> [[XQuery]]<ref name="Grust_Teubner_TDM_2004_Seiten_9-16">{{Quelle|Grust, Teubner (2004)}}, Seiten 9–16</ref>, [[SPARQL]]<ref name="Cyganiak_2005">{{Quelle|Cyganiak (2005)}}</ref> oder auch [[Datalog]]<ref name="Kießling_Köstler_1998">{{Quelle|Kießling, Köstler (1998)}}</ref>. Diese Programme und Anfragen werden üblicherweise zunächst in eine (i. Allg. erweiterte) relationale Algebra übersetzt. Der entstehende Operatorbaum wird dann mit Hilfe relationaler Gesetze transformiert, um eine möglichst effiziente Auswertung der Anfragen zu ermöglichen.<ref name="Ullman_Vol_II_Chapter_11">{{Quelle|Ullman (1989)}}, Chapter 11</ref> | |||
==Geschichte== | |||
Im Jahr 1941 stellte [[Alfred Tarski]] in seinem Papier “On the calculus of relations” erstmals Ideen einer relationalen Algebra vor.<ref name="Tarski 1941">{{Quelle|Tarski (1941)}}</ref> Insbesondere führte er die relationalen Operationen „Vereinigung“, „Durchschnitt“ und „Join“ ein, wobei er sich allerdings auf zweistellige Relationen beschränkte. | |||
= | Am Ende seines Artikels erwähnt er, dass er eigentlich nicht so sehr das Ziel hatte, neue Ergebnisse zu präsentieren, als vielmehr das Interesse an einer bestimmten logischen Theorie zu wecken, die bislang nicht beachtet wurde: | ||
{{Quote|The aim of this paper has been, not so much to present new results, as to awaken interest in a certain neglected logical theory, and to formulate some new problems concerning this theory. (Tarski (1941)<ref name="Tarski 1941"/>)}} | |||
=Beispiele= | Ende der 1960er-Jahre entwickelte [[Edgar Frank Codd|Edgar F. Codd]] am IBM Research Laboratory in San Jose die Grundlagen der heutigen relationalen Algebra.<ref name="Codd 1969">{{Quelle|Codd (1969)}}</ref><ref name="Codd 1970">{{Quelle|Codd (1970)}}</ref> Ob ihn die Arbeit Tarskis dazu inspirierte, ist nicht bekannt. Zu Beginn seines Papiers von 1969 stellt er die Behauptung auf, dass das relationale Modell in vielen Aspekten dem Graphenmodell und dem [[Netzwerkdatenbankmodell|Netzwerkmodell]], die zu dieser Zeit „en vogue“ (franz. „in Mode“) waren, überlegen sei. | ||
{{Quote|The first part of this paper is concerned with an explanation | |||
of a relational view of data. This view (or model) of | |||
data appears to be superior in several respects to the graph or | |||
network model [1, 2] presently in vogue. (Codd (1969)<ref name="Codd 1969"/>) | |||
}} | |||
Er bezieht sich damit auf die Tatsache, dass die Dauer der Beantwortung von Anfragen sehr stark vom Aufbau des jeweiligen Netzwerks abhängt. Sofern Daten abgerufen werden sollen, die im Netzwerk benachbart sind, muss der Benutzer nur sehr kurz auf eine Antwort warten. Sind die gewünschten Daten jedoch im Netzwerk stark verstreut, kann die Wartezeit unzumutbar lang werden. | |||
Die Datenbankentwickler mussten bei der Erstellung eines Netzwerkmodells von vorneherein sämtliche denkbaren Anfragen berücksichtigen, da nachträgliche Änderungen am Datenmodell nur noch sehr schwer umgesetzt werden konnten. Um dieses Problem zu beheben, hatte Codd die Idee, die Daten nicht mehr in einem Netzwerk zu speichern, sondern in Relationen (Tabellen), die je nach Anfrage unterschiedlich miteinander verknüpft werden können: | |||
{{Quote|Future users of large data banks must be protected from | |||
having to know how the data is organized in the machine (the | |||
internal representation (Codd (1970)<ref name="Codd 1970"/>) | |||
}} | |||
Er wagte folgende geradezu prophetische Prognose, dass Datenbanken künftig viele Relationen in gespeicherter Form enthalten würden: | |||
{{Quote|The large, integrated data banks of the future will contain many relations of various degrees in stored form. (Codd (1969)<ref name="Codd 1969"/>)}} | |||
Ende 1970, {{dh}} im selben Jahr, in dem Codds Arbeit publik wurde, stellten [[Rudolf Bayer]] und [[Ed McCreight]] den [[B-Baum]] | |||
vor, eine [[Datenstruktur]], die es ermöglicht, Relationen mit einer großen Anzahl von Tupel so auf einer Festplatte zu speichern, | |||
dass der lesende Zugriff auf Tupel sowie die Modifikation von Tupeln hocheffizient erfolgen | |||
kann.<ref name="Bayer 1970">{{Quelle|Bayer, McCreight (1970)}}</ref><ref name="Bayer 1972">{{Quelle|Bayer, McCreight (1972)}}</ref> | |||
In den 1970er-Jahren begann auf Basis dieser beiden Arbeiten die Erfolgsgeschichte der [[Relationale Datenbank|Relationalen Datenbanken]] | |||
einschließlich der zugehörigen Sprache [[SQL]]. An Codds Arbeitsstätte, {{dh}} am IBM Research Laboratory in San Jose, wurden die Sprache SEQUEL sowie das experimentelle Datenbanksystem [[IBM System R|System R]] entwickelt. Später wurde SEQUEL in [[SQL]] umbenannt. Zu Beginn der 1980er-Jahre gab es für die Anfragesprache SQL die ersten kommerziellen relationalen Datenbanksysteme: [[Db2]] von [[IBM]] und [[Oracle (Datenbanksystem)|Oracle]] von [[Oracle|Relational Software Inc.]]<ref>{{Quelle|Leon, Leon (1999)}}</ref> Heute ist SQL aus der Welt der Datenbanken nicht mehr wegzudenken. Aber auch diverse weitere Sprachen, wie zunächst [[Query by Example|QBE]]<ref name="Ullman_Vol_I_S_195">{{Quelle|Ullman (1988)}}, Seiten 195–210</ref> oder [[QUEL]]<ref name="Ullman_Vol_I_S_185">{{Quelle|Ullman (1988)}}, Seiten 185–195</ref> und später [[Datalog]]<ref name="Kießling_Köstler_1998"/>, [[XQuery]]<ref name="Grust_Teubner_TDM_2004">{{Quelle|Grust, Teubner (2004)}}</ref> oder [[SPARQL]]<ref name="Cyganiak_2005"/>, basieren letztendlich auf der Idee Codds, Relationen zum Speichern von Daten einzusetzen. | |||
==Elemente einer Relationalen Algebra== | |||
Eine [[Relationale Algebra]] ist eine [[Algebraische Struktur|Algebra]], deren Operationen [[Relation]]en auf Relationen abbilden. | |||
[[Datenbankmanagement|Abfragesprachen]] wie [[SQL]], [[SPARQL]], [[XQuery]] etc. liegt eine Relationale Algebra zugrunde. | |||
In derartigen Sprachen werden allerdings üblicherweise [[Tabelle]]n oder noch komplexere Datenstrukturen wie beispielsweise [[JSON]] oder [[XML]] an Stelle von | |||
[[Relation]]en eingesetzt. | |||
'''Unterschiede''' | |||
{| class = "wikitable" style = "table-layout: fixed; max-width: 48em;" | |||
! style="width: 50%;" | Relation | |||
! style="width: 50%;" | Tabelle | |||
|- | |||
| style="vertical-align:top;" | '''duplikatfrei''': Relationen sind {{Menge}}n, daher kommt kein [[Tupel]] zweimal vor. | |||
| style="vertical-align:top;" | '''Duplikate''': Tabellen sind [[Liste]]n, daher können gleiche Tupel mehrfach vorkommen.<br/> | |||
Allerdings gilt dies in SQL nur bei berechneten Tabellen, nicht aber bei gespeicherten Tabellen. | |||
|- | |||
| style="vertical-align:top;" | '''ungeordnet''': Relationen sind Mengen, daher sind die darin enthaltenen Tupel nicht geordnet.<br/> | |||
In einer Relationalen Algebra kann es keine Operation zum Sortieren von Relationen geben. | |||
| style="vertical-align:top;" | '''geordnet''': Tabellen sind (geordnete) Listen, daher ist die Reihenfolge der Tupel festgelegt.<br/> | |||
Allerdings kann man sich bei SQL-Befehlen nicht darauf verlassen, dass das Ergebnis in einer bestimmten Reihenfolge ausgegeben wird. In SQL gibt es daher eine spezielle [[ORDER-BY-Klausel]], um eine bestimmte Reihenfolge zu erzwingen. | |||
|} | |||
Außerdem werden in SQL (Tabellen-)Zeilen (Rows) an Stelle von Tupeln verwendet. In Tabellenzeilen sind die einzelnen Spalten benannt und haben überdies eine Position. | |||
Die klassische [[Tupel]]definition unterscheidet die verschiedenen [[Attribut]]e anhand ihrer Position. Allerdings ist es nicht unüblich, diesen Positionen Namen zu geben. So wird bei einer Raumkoordinate die erste Position {{iAllg}} mit <math>x</math> bezeichnet, die zweite mit <math>y</math> und die dritte mit <math>z</math>. | |||
In Programmiersprachen heißen Tupel, deren Elemente über die Position bestimmt werden, {{Array}}s oder [[Liste]]n: <code>[35, true, 'Hallo']</code>. | |||
Tupel, deren Elemente mittels Identifikatoren unterschieden werden, heißen [[Record]]s, [[Hashmap]]s/[[Hasharray]]s oder auch – {{zB}} in [[JavaScript]] – [[Objekt]]e: <code>{a: 35, b: true, c: 'Hallo'}</code> | |||
Ein Attribut kann als [[geordnetes Paar]] aufgefasst werden, bestehend aus Attributbezeichner und Attributwert. | |||
Abhängig von der Art der Attributbezeichnung unterscheidet man folgende Tupelarten: | |||
{| class = "wikitable" style = "table-layout: fixed; max-width: 48em;" | |||
! style="width: 30%;" | Positionstupel | |||
! style="width: 30%;" | Tupel mit Attributnamen | |||
! style="width: 40%;" | Rows (Tabellenzeilen) | |||
|- | |||
| style="vertical-align:top;" | Die Attribute werden über ihre Position bestimmt, {{dh}}, der Attributbezeichner ist eine natürliche Zahl. | |||
| style="vertical-align:top;" | Die Attribute werden über ihre Namen bestimmt, {{dh}}, der Attributbezeichner ist eine Zeichenkette. | |||
| style="vertical-align:top;" | Die Attribute werden über ihren Namen oder ihre Position bestimmt, {{dh}}, der Attributbezeichner ist eine Zeichenkette oder eine natürliche Zahl. | |||
|- | |||
| style="vertical-align:top;" | <code>t =<br/>['x', 'y', 'z']</code> | |||
| style="vertical-align:top;" | <code>t =<br/>{a:'x', b:'y', c:'z'}</code> | |||
| style="vertical-align:top;" | <code>t =<br/>{a/0:'x', b/1:'y', c/2:'z'}</code><br/> | |||
Diese Art von Tupeln wird von üblichen Programmiersprachen nicht unterstützt. | |||
|- | |||
| style="vertical-align:top;" | <code>t[1] == 'y'</code> | |||
| style="vertical-align:top;" | <code>t['b'] == t.b == 'y'</code> | |||
| style="vertical-align:top;" | <code>t[1] == t['b'] == t.b == 'y'</code> | |||
|} | |||
In SQL werden benannte Attribute, {{dh}} Tupel mit Attributnamen verwendet. Allerdings ist es üblich, dass in Hostsprachen auf beide Arten auf ein Attribut zugegriffen werden kann. Beispielsweise stellt JDBC (Java Database Connectivity) die Methode <code>getObject</code> zur Verfügung, die sowohl Integer- als auch Stringwerte als Attributbezeichner akzeptiert.<ref>{{Quelle|Taylor (2003)}}, Seite 332–333</ref> | |||
Für Datenstrukturen wie <code>JSON</code> oder <code>XML</code> gelten analoge Aussagen: | |||
Es gibt an Stelle von Relationen allgemeinere {{Container}}, deren Elemente geordnet sind und | |||
Duplikate enthalten können. Außerdem gibt es [[Individuum|Individuen]], die als verallgemeinerte | |||
Tupel aufgefasst werden können. Dabei kommen sowohl Positions- als auch benannte Attribute zum Einsatz. | |||
==Definitionen ([[Wolfgang Kowarschick|Kowarschick]] (2018))== | |||
=== Tupelmengen und Relationenschemata=== | |||
====Positionstupel==== | |||
Es seien <math>n \in \mathbb{N}_0</math> und <math>D_1, \ldots, D_n</math> [[Domäne]]n, {{dh}} nichtleere {{Menge}}n. | |||
Die geordnete Liste <math>R = [D_1, \ldots, D_n]</math> heißt '''Relationenschema (für Positionstupel)'''. | |||
Die [[kartesisches Produkt|kartesische Produkt]] | |||
<div class="formula"><math>T := T_R := T(D_1, \ldots, D_n) := D_1 \times \ldots \times D_n = {\Large ⨉}_{i=1}^nD_i</math></div> | |||
enthält | |||
alle '''Positionstupel''' der Art <math>(v_1, \ldots, v_n)</math>, wobei <math>v_i \in D_i</math>. | |||
(Es gilt also insbesondere <math>T() = \{()\}</math>.) | |||
Mittels <math>t[i]</math> greift man auf das <math>i</math>-te Element <math>v_i</math> eines zugehörigen Tupels <math>t = (v_1, \ldots, v_n)</math> zu. | |||
Eine [[Relation]] <math>r := r_R := r(D_1,\dots, D_n) \subset T_R</math> ist eine Relation mit Relationenschema <math>R</math>, {{dh}} | |||
<math>r_R</math> enthält ausschließlich Positionstupel, die dem Relationenschema <math>R</math> genügen. | |||
====Attributtupel==== | |||
Es seien <math>a_1, \ldots, a_n</math> (<math>n \in \mathbb{N}_0</math>) ''unterschiedliche'' Attributnamen (<math>a_i \ne a_j</math> für <math>i \ne j</math>) | |||
und <math>D_1, \ldots, D_n</math> die zugehörige Domänen, {{dh}} nichtleere {{Menge}}n. Die Domäne <math>D_i</math> enthält alle [[Wert]]e, die das Attribut <math>a_i</math> annehmen kann. | |||
Ein Paar <math>(a_i, D_i) = a_i : D_i</math> heißt '''Attributdefinition'''. <math>a_i</math> ist der der Name des Attributs ('''Attributname'''), | |||
<math>D_i</math> die '''Domäne'''. | |||
Die Menge <math>R = \{(a_1, D_1), \ldots, (a_n, D_n)\} = \{a_1 : D_1, \ldots, a_n : D_n\}</math> heißt '''Relationenschema (für Attributtupel)'''. | |||
Die Menge | |||
<div class="formula"><math>T := T_R := T(a_1: D_1, \ldots, a_n: D_n)</math></div> | |||
enthält alle '''Attributtupel''' <math>t = \{(a_1, v_1), \ldots, (a_n, v_n)\} = \{a_1 : v_1, \ldots, a_n : v_n\}</math>, wobei <math>v_i \in D_i</math>. | |||
Man beachte, dass es bei einem derartigen Tupel nicht auf die Reihenfolge der Attribute ankommt, da ein Attributtupel eine '''Menge''' von Paaren ist. | |||
Mittels <math>t[a_i] = t.a_i = \bigcap\{v : (a_i, v) \in t \}</math> greift man auf den Wert <math>v_i</math> des Attributs <math>a_i</math> eines zugehörigen Tupels <math>t</math> zu. | |||
Eine [[Relation]] <math>r := r_R := r(a_1: D_1, \ldots, a_n: D_n)</math> ist eine Relation mit dem Relationenschema <math>R</math>, {{dh}} | |||
<math>r_R \subset T_R</math> enthält Positionstupel, die dem Relationenschema <math>R</math> genügen. | |||
Die Menge <math>T(D_1, \ldots, D_n)</math> kann mit der Menge <math>T(1: D_1, \ldots, n: D_n)</math> identifiziert werden ({{dh}}, die zugehörigen Tupel können | |||
[[bijektiv]] aufeinander abgebieldet werden). Ebenso kann ein Relation <math>r(D_1, \ldots, D_n)</math> mit einer Relation | |||
<math>r(1: D_1, \ldots, n:D_n)</math> identifiziert werden. | |||
====Attributierte Positionstupel==== | |||
Die Menge | |||
<div class="formula"><math>T(a_1/1: D_1, \ldots, a_n/n: D_n)</math></div> | |||
enthalte alle attributierten Tupel deren Attribute zusätzlich mit einer Position versehen sind. | |||
Das heißt, sie enthält alle Tupel der Art <math>(a_1/1:v_1, \ldots, a_n/n:v_n)</math>, wobei <math>v_i \in D_i</math>. | |||
Mittels <math>t[a_i]</math> oder auch <math>t.a_i</math> greift man auf den Wert <math>v_i</math> des Attributs <math>a_i</math> eines zugehörigen Tupels <math>t</math> zu. Und mittels <math>t[i]</math> greift man auf das <math>i</math>-te Element von <math>t</math> zu. | |||
In einer Relationalen Algebra ist eine '''Relation''' <math>r</math> {{iAllg}} eine '''Teilmenge einer Tupelmenge''' <math>T(a_1/1: D_1, \ldots, a_n/n: D_n)</math>. | |||
Das heißt, jedes Tupel <math>t \in r</math> besteht aus einer geordneten Menge von [[Attribut]]en, deren Werte vorgegebenen Domänen entstammen. | |||
<math>(a_1/1: D_1, \ldots, a_n/n: D_n)</math> heißt das '''Schema''' der Relation <math>r</math>. | |||
<math>\mathcal R</math> sei die Menge aller Relationen. Die [[Potenzmenge]] einer der zuvor definierten Tupelmengen ist stets eine | |||
Teilmenge von <math>\mathcal R</math>: | |||
<div class="formula"><math>\mathscr{P}(T(a_1/1: D_1, \ldots, a_n/n: D_n)) \subset \mathcal R</math></div> | |||
Jede Relation mit Schema <math>T(a_1/1: D_1, \ldots, a_n/n: D_n)</math> kann auch als Relation mit Schema | |||
<math>T(a_1: D_1, \ldots, a_n: D_n)</math> bzw. mit Schema <math>T(D_1, \ldots, D_n)</math> aufgefasst werden. | |||
===Relationale Algebra=== | |||
Eine [[Algebraische Struktur|Algebra]] <math>\mathfrak{R} = (\mathcal R, id, π, σ, \times, \div, \cup, \cap, \setminus)</math> heißt [[Relationale Algebra]] wenn die Trägermenge <math>R</math> eine [[Menge (Mengenlehre)|Menge]] von [[Relation|Relationen]] mit benannten Attributen ist. | |||
* <math>id: \mathcal R \rightarrow \mathcal R</math> ist die so genannte Identitätsfunktion: Es gilt stets <math>id(r) = r</math> | |||
* <math>π</math> ist eine [[abzählbar]]e Menge von (partiellen) Projektionsfunktionen <math>π_{f_1 \,\text{as}\, a_1, \,\ldots, \,f_n \,\text{as}\, a_n}: \mathcal R \rightharpoonup \mathcal R</math>. Diese berechnen mit Hilfe der Funktionen <math>f_i</math> für jedes Tupel einer Relation <math>r</math> insgesamt <math>n</math> neue Attribue. Die neuen Attribute haben die Namen <math>a_1</math> bis <math>a_n</math>. Jeder dieser Funktionen werden die Attribute des jeweiligen Tupels als [[Argument]]e übergeben. Das heißt, eine Projektionsfunktion kann nur auf diejenigen Relationen angewendet werden, deren Attribute kompatibel mit den Projektionsfunktionen sind. | |||
* <math>σ</math> ist eine [[abzählbar]]e Menge von (partiellen) Selektionsfunktionen <math>σ_b: \mathcal R \rightharpoonup \mathcal R</math>. Mit ihrer Hilfe werden aus einer Relation <math>r</math> diejenigen Tupel selektiert, die die Bedingung <math>b</math> erfüllen, {{dh}}, für die Funktion <math>b</math> den Wert <code>true</code> liefert, wenn sie auf das jeweilige Tupel angewendet wird. Eine Selektionsfunktion kann nur auf diejenigen Relationen angewendet werden, deren Attribute kompatibel mit den Funktion <math>b</math> sind. | |||
* <math>\times: \mathcal R, \mathcal R \rightharpoonup \mathcal R</math> ist das kartesische Produkt, das zwei Relationen zu einer Relation verknüpft. Für jede mögliche Kombination von zwei Tupeln der Urbildrelationen ist die [[Konkatenation]] der beiden Tupel Element der Bildrelation. Das kartesische Produkt kann nur auf Relationenpaare angewendet werden, deren Attributnamen sich unterscheiden (da ein Tupel mit benannten Attributen keinen Attributnamen mehrfach enthalten kann). | |||
* <math>\div: \mathcal R, \mathcal R \rightharpoonup \mathcal R</math> ist die Division. Im Prinzip ist dies die Umkehrfunktion des kartesischen Produktes. | |||
* <math>\cup: \mathcal R, \mathcal R \rightharpoonup \mathcal R</math> ermittelt die Vereinigung zweier (strukturgleicher) Relationen. | |||
* <math>\cap: \mathcal R, R \rightharpoonup \mathcal R</math> ermittelt den Durchschnitt zweier (strukturgleicher) Relationen. | |||
* <math>\setminus: \mathcal R, \mathcal R \rightharpoonup \mathcal R</math> ermittelt die Differenz zweier (strukturgleicher) Relationen. | |||
==Relationale Operationen== | |||
===Identität=== | |||
[[Datei:Relational Algebra Single Table Identity.svg | mini|200px | rechts |gerahmt|Die Identitätsfunktion verändert eine Tabelle nicht.]] | |||
Die Identitätsfunktion der [[Relationale Algebra|Relationalen Algebra]] ist eine triviale Funktion: | |||
Sie bildet eine Relation (Tabelle) auf sich selbst ab: | |||
<div class="formula"> | |||
<math>id: \mathcal R \rightarrow \mathcal R</math><br /> | |||
<math>id(r) = r</math> | |||
</div> | |||
Die Identiätsfunktion liefert als Ergebnisalso stets die Urbildrelation zurück. Das heißt, sie verändert eine Relation nicht. | |||
Diese Funtion ist ''idempotent'': | |||
<div class="formula"> | |||
<math>id(id(r)) = id(r) = r</math> | |||
</div> | |||
Die Identitätsfunktion ist eine der wenigen [[totale Funktion|totalen Funktionen]] der Relationalen Algebra. Das heißt, sie kann auf jede beliebige Relation angewendet werden. | |||
In [[SQL]] wird eine derartige Funktion benötigt, um den gesamten Inhalt einer Relation zu erfragen, da in jeder | |||
SQL-Anweisung zum Lesen von Dateninhalten mindestens eine relationale Operation enthalten sein muss. | |||
In [[SQL 92]]<ref>{{Quelle|Date, Darwen (1993)}}</ref> | |||
wurde zu diesem Zweck der Befehl <code>table</code> eingeführt, dessen einzige Aufgabe es ist, die ihm übergebene | |||
Tabelle (Relation) vollständig auszugeben. Dieser Befehl ist jedoch nicht notwendig, da eine Projektion, die alle Attribute einer Relation unverändert zurück gibt, | |||
ebenfalls als Identitätsfunktion verwendet werden kann (siehe nachfolgenden Abschnitt). | |||
[[PostgreSQL]] beispielsweise unterstützt ihn dennoch.<ref>https://www.postgresql.org/docs/current/static/sql-select.html PostgreSQL: Select</ref> | |||
'''Beispiel''' | |||
{| | |||
! style="text-align:center;" | <math>r</math> | |||
! style="text-align:center;" | → | |||
! style="text-align:center;" | <math>id(r)</math> | |||
|- | |||
| | |||
{| class="wikitable" style="margin: 0.5em 0 0 0" | |||
! <math>a_1</math> || <math>a_2</math> || <math>a_3</math> || <math>a_4</math> || <math>a_5</math> | |||
|- | |||
| a || b || c || 5 || 13 | |||
|- | |||
| a || d || b || 7 || 17 | |||
|- | |||
| c || f || g || 3 || 21 | |||
|} | |||
| → <br/> | |||
| | |||
{| class="wikitable" style="margin: 0.5em 0 0 0" | |||
! <math>a_1</math> || <math>a_2</math> || <math>a_3</math> || <math>a_4</math> || <math>a_5</math> | |||
|- | |||
| a || b || c || 5 || 13 | |||
|- | |||
| a || d || b || 7 || 17 | |||
|- | |||
| c || f || g || 3 || 21 | |||
|} | |||
|} | |||
'''SQL''' | |||
<source lang="sql"> | |||
TABLE r; -- seit SQL 92 | |||
SELECT a1, a2, a3, a4, a5 FROM r; | |||
SELECT * FROM r; | |||
</source> | |||
Siehe auch [[Händler-Datenbank (SQL-Beispiel)/Identität]] | |||
===Projektion=== | |||
====Einfache Projektion==== | |||
[[Datei:Relational Algebra Single Table Projection.svg | mini|200px | rechtsFile:Relational Algebra Single Table Projection.svg |gerahmt|Eine Projektionsfunktion entfernt Spalten aus einer Tabelle.]] | |||
Es seien <math>A = (a_1/1: D_1, \ldots, a_n/n:D_n)</math> und <math>B=(b_1/1: D'_1, \ldots, b_m/m:D'_m)</math> zwei Schemata, mit | |||
<math>\{b_1, \ldots, b_m\} \subset \{a_1, \ldots, a_n\}</math> und <math>D_i = D'_j</math>, falls <math>a_i = b_j</math> | |||
Die Projektionsfunktionen <math>π</math> wurden von Codd eingeführt, um Attribute einer Relation entfernen können. Eine Projektionsfunktion | |||
<div class="formula"> | |||
<math>π_{b_1, \ldots, b_m}: \mathscr{P} T(A) \rightarrow \mathscr{P}T(B)</math><br /> | |||
</div> | |||
dient also dazu, bestimmte Spalten aus einer beliebigen ({{dh}} gespeicherten oder berechneten Tabelle) zu selektieren. | |||
Wenn <math>r \in A</math> eine Relation ist, | |||
dann ist <math>π_{b_1, \ldots, b_m}(r) \in B</math> diejenige Tabelle, die aus <math>r</math> entsteht, wenn man alle Spalten aus <math>r</math> | |||
entfernt, die nicht in {b_1, \ldots, b_m} enthalten sind. Dabei entstehende Duplikate müssen ebenfalls entfernt werden, sofern die Relationale Algebra – wie von Codd | |||
ursprünglich gefordert – mengenbasiert ist. In SQL werden nur gespeicherte Tabellen als duplikatifreie Mengen behandelt, | |||
berechnete Tabellen sind dagegen Multimengen, die Duplikate enthalten dürfen. | |||
Außerdem führte Codd noch Permutationsfunktionen ein, um die Reihenfolge der Attribute zu ändern.<ref name="Codd 1969">{{Quelle|Codd (1969)}}</ref><ref name="Codd 1970">{{Quelle|Codd (1970)}}</ref> Der Begriff [[Permutation]] ist allerdings nur für Tupel mit Positionsattributen sinnvoll (<code>[10,30]</code> und <code>[30,10]</code> bezeichnen zwei verschiedene Punkte in einer Ebene). Für Tupel mit Attributnamen benötigt man dagegen keine Funktion, die Attribute vertauscht, da benannte Attribute keine Positionen besitzen (<code>{x: 10, y: 30}</code> und <code>{y: 30, x: 10}</code> bezeichnen denselben Punkt in einer Ebene). Hier muss eine „Permutationsfunktion“ Attributnamen umbenennen können. Die obige Definition beinhaltet bereits beide Arten von Permutation. Daher wir hier keine spezielle Permutationsfunktion benötigt. | |||
====Erweiterte Projektion==== | |||
[[Datei:Relational Algebra Single Table Projection Extended.svg | mini|200px | rechts |gerahmt|Genauer: Eine Projektionsfunktion berechnet neue Spalteninhalte aus den alten Spalteninhalten. Dabei entstehende Duplikattupel werden ebenfalls entfernt.]] | |||
In der Zwischenzeit werden die Projektionsfunktionen allgemeiner definiert. Sie berechnen für jedes Tupel einer Relation aus dessen Attributwerten ein neues Tupel. | |||
Es seien <math>A = (a_1/1: D_1, \ldots, a_n/n:D_n)</math> und <math>B=(b_1/1: D'_1, \ldots, b_m/m:D'_m)</math> zwei Schemata. | |||
Die Domänen brauchen nicht in irgendeine besondereren Beziehung zueinander zu stehen. Darüber hinaus gebe es $m$ Funktionen | |||
f_j: T(A) \rightarrow D'_j, die A-Tupel auf Elemente der zugehörigen Domäne <math>D_j</math> abbilden. | |||
Die zugehörige Projektionsfunktion | |||
<div class="formula"> | |||
<math>π_{f_1 \,\text{as}\, b_1, \ldots, f_m \,\text{as}\, b_m}: \mathscr{P}T(A) \rightarrow \mathscr{P}T(B)</math><br /> | |||
</div> | |||
bildet jedes A-Tupel einer zugehörigen Relation <math>r</math> auf ein B-Tupel ab, indem sie den Wert von <math>b_j</math> mittels | |||
<math>f_j</math> berechnet. | |||
Die einfache Projektion ist ein Spezialfall dieser allgemeineren Definition, | |||
wenn man <math>b_j</math> sowohl als Attributnamen also auch als Funktion auffasst: | |||
<math>b_j</math> entspricht <math>b_j \,\text{as}\, b_j</math>, wobei die Funktion <math>b_j</math> folgendermaßen definiert wird: | |||
<math>b_j((a_1:v_1, \ldots, a_n:v_n)) = v_i</math>, falls der Attributename <math>b_j</math> gleich <math>a_i</math> ist. | |||
Beachten Sie bitte: Die folgenden Beispiele funktionieren sowohl für Positionsattribute als auch für benannte Attribute als auch für Rows, bei denen Attribute sowohl eine Position als auch einen Namen haben. | |||
'''Beispiele''' | |||
{| | |||
! style="text-align:center;" | <math>r</math> | |||
! style="text-align:center;" | → | |||
! style="text-align:center;" | <math>π_{a_4, \,a_1}(r)</math> | |||
! | | |||
! style="text-align:left; padding: 0.2em" | SQL | |||
|- | |||
| | |||
{| class="wikitable" style="margin: 0.5em 0 0 0" | |||
! <math>a_1</math> || <math>a_2</math> || <math>a_3</math> || <math>a_4</math> || <math>a_5</math> | |||
|- | |||
| c || b || c || 5 || 13 | |||
|- | |||
| a || d || g || 7 || 17 | |||
|- | |||
| a || f || g || 3 || 21 | |||
|} | |||
| → <br/> | |||
| | |||
{| class="wikitable" style="margin: 0.5em 0 0 0" | |||
! <math>a_4</math> || <math>a_1</math> | |||
|- | |||
| 5 || c | |||
|- | |||
| 7 || a | |||
|- | |||
| 3 || a | |||
|} | |||
| | |||
| style="vertical-align:top;" | <code>SELECT a4, a1 FROM r</code> | |||
|} | |||
'''Anmerkung''': <math>π_{a_4, \,a_1}(r)</math> ist eine Abkürzung für <math>π_{a_4 \rm{\,as\,} a_4, \,a_1 \rm{\,as\,} a_1}(r)</math>. | |||
Attribute können auch berechnet und (um-)benannt werden. Duplikate, wie {{zB}} (a, g, 24), werden in der Relationalen Algebra automatisch entfernt. In SQL werden Duplikate nur dann entfernt, wenn man das Schlüsselwort „<code>DISTINCT</code>“ angibt. SQL liegt eine so genannte [[Multimenge]]n-Semantik zu Grunde. | |||
{| | |||
! style="text-align:center;" | <math>r</math> | |||
! style="text-align:center;" | → | |||
! style="text-align:center;" | <math>π_{a_1, \,a_3, \,a_4+a_5 \rm{\,as\,} b_1}(r)</math> | |||
! | | |||
! style="text-align:left; padding: 0.2em" | SQL | |||
|- | |||
| style="vertical-align:top;" | | |||
{| class="wikitable" style="margin: 0.5em 0 0 0" | |||
! <math>a_1</math> || <math>a_2</math> || <math>a_3</math> || <math>a_4</math> || <math>a_5</math> | |||
|- | |||
| c || b || c || 5 || 13 | |||
|- | |||
| a || d || g || 7 || 17 | |||
|- | |||
| a || f || g || 3 || 21 | |||
|} | |||
| → <br/> | |||
| style="vertical-align:top;" | | |||
{| class="wikitable" style="margin: 0.5em 0 0 0" | |||
! <math>a_4</math> || <math>a_3</math> || <math>b_1</math> | |||
|- | |||
| c || a || 18 | |||
|- | |||
| a || g || 24 | |||
|} | |||
| | |||
| style="vertical-align:top;" | <code>SELECT DISTINCT a4, a3, a4+a5 AS b1<br/>FROM r</code> | |||
|} | |||
Die Identitätsfunktion kann – wie es bereits weiter oben angesprochen wurde – mit Hilfe der Projektionsfunktion nachgebildet werden. Allerdings benötigt man für jede | |||
Relation eine spezielle Projektionsfunktion. In der Projektiosnliste müssen alle Attribute der zugehörigen Funktion genau einmal aufgeführt werden: | |||
{| | |||
! style="text-align:center;" | <math>r</math> | |||
! style="text-align:center;" | → | |||
! style="text-align:center;" | <math>π_{a_1, \,a_2, \,a_3, \,a_4, \,a_5}(r)</math> | |||
! | | |||
!! style="text-align:left; padding: 0.2em" | SQL | |||
|- | |||
| style="vertical-align:top;" | | |||
{| class="wikitable" style="margin: 0.5em 0 0 0" | |||
! <math>a_1</math> || <math>a_2</math> || <math>a_3</math> || <math>a_4</math> || <math>a_5</math> | |||
|- | |||
| c || b || c || 5 || 13 | |||
|- | |||
| a || d || g || 7 || 17 | |||
|- | |||
| a || f || g || 3 || 21 | |||
|} | |||
| → <br/> | |||
| style="vertical-align:top;" | | |||
{| class="wikitable" style="margin: 0.5em 0 0 0" | |||
! <math>a_1</math> || <math>a_2</math> || <math>a_3</math> || <math>a_4</math> || <math>a_5</math> | |||
|- | |||
| c || b || c || 5 || 13 | |||
|- | |||
| a || d || g || 7 || 17 | |||
|- | |||
| a || f || g || 3 || 21 | |||
|} | |||
| | |||
| style="vertical-align:top;" | <code>SELECT a1, a2, a3, a4, a5 FROM r;</code> | |||
<!-- --><code>SELECT r.* FROM r;</code> | |||
<!-- --><code>SELECT * FROM r;</code> | |||
|} | |||
In SQL kann man abkürzend den Stern „<code>*</code>“ verwenden. Dieser bezeichnet alle Attribute der aktuellen Relation. | |||
Mit <code>r.*</code> werden in SQL alle Attribute der Relation <code>r</code> bezeichnet. Für das obige Beispiel kann man in der | |||
Relationalen Algebra analog folgenden Abkürzungen definieren: | |||
<math> r = π_{a_1, \,a_2, \,a_3, \,a_4, \,a_5}(r) = π_{r.*}(r) = π_{*}(r) = id(r)</math> | |||
Mit dem Stern-Operator man also eine alternative Definition der Identitätsfunktion mit Hilfe des Projektionsoperators angeben, die ohne die Attributnamen der jeweiligen Relation auskommt. (In SQL ist die Verwendung des Sternoperator allerdings verpönt, da sich die Attribute einer Tabelle im Laufe der Zeit ändern können ([[Schemaevolution]]) und sich damit die Bedeutung des Sterns ändert. Das heißt, Anfragen, die einen <code>*</code> enthalten, können plötzlich weniger, mehr oder andere Spalten im Ergebnis liefern.) | |||
Siehe auch [[Händler-Datenbank (SQL-Beispiel)/Projektion]] | |||
===Selektion=== | |||
[[Datei:Relational Algebra Single Table Selection.svg| mini|200px | rechts |gerahmt|Eine Selektionsfunktion entfernt Zeilen (= Tupel) aus einer Tabelle.]] | |||
Eine Selektionsfunktion entfernt Zeilen (= [[Tupel]]) aus einer Tabelle. | |||
{| | |||
! style="text-align:center;" | <math>r</math> | |||
! style="text-align:center;" | → | |||
! style="text-align:center;" | <math>σ_{a_1= \tt{'a'}}(r)</math> | |||
! | | |||
!! style="text-align:left; padding: 0.2em" | SQL | |||
|- | |||
| style="vertical-align:top;" | | |||
{| class="wikitable" style="margin: 0.5em 0 0 0" | |||
! <math>a_1</math> || <math>a_2</math> || <math>a_3</math> || <math>a_4</math> || <math>a_5</math> | |||
|- | |||
| c || b || c || 5 || 13 | |||
|- | |||
| a || d || g || 7 || 17 | |||
|- | |||
| a || f || g || 3 || 21 | |||
|} | |||
| → <br/> | |||
| style="vertical-align:top;" | | |||
{| class="wikitable" style="margin: 0.5em 0 0 0" | |||
! <math>a_1</math> || <math>a_2</math> || <math>a_3</math> || <math>a_4</math> || <math>a_5</math> | |||
|- | |||
| a || d || g || 7 || 17 | |||
|- | |||
| a || f || g || 3 || 21 | |||
|} | |||
| | |||
| style="vertical-align:top;" | <code>SELECT *<br/>FROM r<br/>WHERE a1 = 'a';</code> | |||
|} | |||
{| | |||
! style="text-align:center;" | <math>r</math> | |||
| → | |||
! style="text-align:center;" | <math>σ_{a_1 = \tt{'a'} \,\wedge\, a_5<21}(r)</math> | |||
! | | |||
!! style="text-align:left; padding: 0.2em" | SQL | |||
|- | |||
| style="vertical-align:top;" | | |||
{| class="wikitable" style="margin: 0.5em 0 0 0" | |||
! <math>a_1</math> || <math>a_2</math> || <math>a_3</math> || <math>a_4</math> || <math>a_5</math> | |||
|- | |||
| c || b || c || 5 || 13 | |||
|- | |||
| a || d || g || 7 || 17 | |||
|- | |||
| a || f || g || 3 || 21 | |||
|} | |||
| → <br/> | |||
| style="vertical-align:top;" | | |||
{| class="wikitable" style="margin: 0.5em 0 0 0" | |||
! <math>a_1</math> || <math>a_2</math> || <math>a_3</math> || <math>a_4</math> || <math>a_5</math> | |||
|- | |||
| a || d || g || 7 || 17 | |||
|} | |||
| | |||
| style="vertical-align:top;" | <code>SELECT *<br/>FROM r<br/>WHERE a1 = 'a' AND a5 < 20;</code> | |||
|} | |||
Siehe auch [[Händler-Datenbank (SQL-Beispiel)/Selektion]] | |||
===Kartesisches Produkt=== | |||
[[Datei:Relational Algebra Cartesian Product.svg | mini|440px | rechts |gerahmt|Das Kartesische Produkt verknüpft alle möglichen Tupelpaare zu jeweils einem Tupel, das alle Attribute beider Tupel enthält.]] | |||
Das Kartesische Produkt verknüpft alle möglichen Tupelpaare zweier Relationen zu jeweils einem Tupel, das alle Attribute beider Tupel enthält. | |||
{| | |||
! style="text-align:center;" | <math>r</math> | |||
! style="text-align:center;" | <math>\times</math> | |||
! style="text-align:center;" | <math>s</math> | |||
! style="text-align:center;" | → | |||
! style="text-align:center;" | <math>r </math> | |||
! | | |||
!! style="text-align:left; padding: 0.2em" | SQL | |||
|- | |||
| style="vertical-align:top;" | | |||
{| class="wikitable" style="margin: 0.5em 0 0 0" | |||
! <math>a_1</math> || <math>a_2</math> || <math>a_3</math> || <math>a_4</math> | |||
|- | |||
| a || b || c || d | |||
|- | |||
| aa || bb || cc || dd | |||
|- | |||
| aaa || bbb || ccc || ddd | |||
|} | |||
| <math>\times</math> <br/> <br/> <br/> <br/> | |||
| style="vertical-align:top;" | | |||
{| class="wikitable" style="margin: 0.5em 0 0 0" | |||
! <math>b_1</math> || <math>b_2</math> | |||
|- | |||
| true || 3.14 | |||
|- | |||
| false || 2.71 | |||
|} | |||
| → <br/> <br/> <br/> <br/> | |||
| style="vertical-align:top;" | | |||
{| class="wikitable" style="margin: 0.5em 0 0 0" | |||
! <math>a_1</math> || <math>a_2</math> || <math>a_3</math> || <math>a_4</math> || <math>b_1</math> || <math>b_2</math> | |||
|- | |||
| a || b || c || d || true || 3.14 | |||
|- | |||
| aa || bb || cc || dd || true || 3.14 | |||
|- | |||
| aaa || bbb || ccc || ddd || true || 3.14 | |||
|- | |||
| a || b || c || d || false || 2.71 | |||
|- | |||
| aa || bb || cc || dd || false || 2.71 | |||
|- | |||
| aaa || bbb || ccc || ddd || false || 2.71 | |||
|} | |||
| | |||
| style="vertical-align:top;" | <code>SELECT *<br/>FROM r, s</code> | |||
<code>SELECT *<br/>FROM r CROSS JOIN s</code> | |||
|} | |||
Siehe auch [[Händler-Datenbank (SQL-Beispiel)/Kartesisches Produkt]] | |||
===Join=== | |||
Ein Join ist formal nichts weiter, als ein Kartesisches Produkt gefolgt von einer Selektion. | |||
Siehe auch [[Händler-Datenbank (SQL-Beispiel)/Join]] | |||
<!-- | |||
===Mengen-Operationen: Vereinigung, Durchschnitt, Differenz, Symmetrische Differenz=== | |||
<div> | |||
<span style="float: right;"> [[Datei:SymmetrischeDifferenzTabellen.png | mini|200px|gerahmt|Symmetrische Differenz]] </span> | |||
<span style="float: right;"> [[Datei:DifferenzTabellen.png | mini|200px|gerahmt|Differenz]] </span> | |||
<span style="float: right;"> [[Datei:DurchschnittTabellen.png | mini|200px|gerahmt|Durchschnitt]] </span> | |||
<span style="float: right;"> [[Datei:VereinigungTabellen.png | mini|200px|gerahmt|Vereinigung]] </span> | |||
</div> | |||
--> | |||
{{TBD|<math>⨝</math>, <math>⟕</math>, <math>⟖</math>, <math>⟗</math>, <math>\triangle</math>}} | |||
==Quellen== | |||
<references/> | <references/> | ||
<ol> | <ol> | ||
<li value=" | <li value="14">{{Quelle|Ullman (1988)}}</li> | ||
<li>{{Quelle|Ullman (1989)}}</li> | |||
<li>{{Quelle|Garcia-Molina, Ullman, Widom (2002)}}</li> | |||
<li>{{Quelle|Elmasri, Navathe (2011)}}</li> | |||
</ol> | </ol> | ||
==Siehe auch== | |||
* [[Händler-Datenbank (SQL-Beispiel)]] | |||
[[Kategorie:Algebraische Struktur]] | [[Kategorie:Algebraische Struktur]] | ||
[[Kategorie:Mathematische Definition]] | [[Kategorie:Mathematische Definition]] | ||
[[Kategorie:Datenmanagement]] | [[Kategorie:Datenmanagement]] | ||
[[Kategorie:Glossar]] |
Aktuelle Version vom 25. Oktober 2019, 11:48 Uhr
Dieser Artikel erfüllt die GlossarWiki-Qualitätsanforderungen nur teilweise:
Korrektheit: 2 (teilweise überprüft) |
Umfang: 2 (wichtige Fakten fehlen) |
Quellenangaben: 3 (wichtige Quellen vorhanden) |
Quellenarten: 5 (ausgezeichnet) |
Konformität: 5 (ausgezeichnet) |
In der Theorie der Datenbanken versteht man unter einer relationalen Algebra oder Relationenalgebra eine Menge von Operationen zur Manipulation von Relationen. Sie ermöglicht es, Relationen zu filtern, zu verknüpfen, zu aggregieren oder anderweitig zu modifizieren, um Anfragen an eine Datenbank zu formulieren.[1][2]
Normalerweise werden Anfragen und Programme nicht direkt in einer relationalen Algebra formuliert, sondern in einer deklarativen Sprache wie SQL,[3] XQuery[4], SPARQL[5] oder auch Datalog[6]. Diese Programme und Anfragen werden üblicherweise zunächst in eine (i. Allg. erweiterte) relationale Algebra übersetzt. Der entstehende Operatorbaum wird dann mit Hilfe relationaler Gesetze transformiert, um eine möglichst effiziente Auswertung der Anfragen zu ermöglichen.[7]
Geschichte
Im Jahr 1941 stellte Alfred Tarski in seinem Papier “On the calculus of relations” erstmals Ideen einer relationalen Algebra vor.[8] Insbesondere führte er die relationalen Operationen „Vereinigung“, „Durchschnitt“ und „Join“ ein, wobei er sich allerdings auf zweistellige Relationen beschränkte.
Am Ende seines Artikels erwähnt er, dass er eigentlich nicht so sehr das Ziel hatte, neue Ergebnisse zu präsentieren, als vielmehr das Interesse an einer bestimmten logischen Theorie zu wecken, die bislang nicht beachtet wurde:
The aim of this paper has been, not so much to present new results, as to awaken interest in a certain neglected logical theory, and to formulate some new problems concerning this theory. (Tarski (1941)[8])
Ende der 1960er-Jahre entwickelte Edgar F. Codd am IBM Research Laboratory in San Jose die Grundlagen der heutigen relationalen Algebra.[9][10] Ob ihn die Arbeit Tarskis dazu inspirierte, ist nicht bekannt. Zu Beginn seines Papiers von 1969 stellt er die Behauptung auf, dass das relationale Modell in vielen Aspekten dem Graphenmodell und dem Netzwerkmodell, die zu dieser Zeit „en vogue“ (franz. „in Mode“) waren, überlegen sei.
The first part of this paper is concerned with an explanation of a relational view of data. This view (or model) of data appears to be superior in several respects to the graph or network model [1, 2] presently in vogue. (Codd (1969)[9])
Er bezieht sich damit auf die Tatsache, dass die Dauer der Beantwortung von Anfragen sehr stark vom Aufbau des jeweiligen Netzwerks abhängt. Sofern Daten abgerufen werden sollen, die im Netzwerk benachbart sind, muss der Benutzer nur sehr kurz auf eine Antwort warten. Sind die gewünschten Daten jedoch im Netzwerk stark verstreut, kann die Wartezeit unzumutbar lang werden. Die Datenbankentwickler mussten bei der Erstellung eines Netzwerkmodells von vorneherein sämtliche denkbaren Anfragen berücksichtigen, da nachträgliche Änderungen am Datenmodell nur noch sehr schwer umgesetzt werden konnten. Um dieses Problem zu beheben, hatte Codd die Idee, die Daten nicht mehr in einem Netzwerk zu speichern, sondern in Relationen (Tabellen), die je nach Anfrage unterschiedlich miteinander verknüpft werden können:
Future users of large data banks must be protected from having to know how the data is organized in the machine (the internal representation (Codd (1970)[10])
Er wagte folgende geradezu prophetische Prognose, dass Datenbanken künftig viele Relationen in gespeicherter Form enthalten würden:
The large, integrated data banks of the future will contain many relations of various degrees in stored form. (Codd (1969)[9])
Ende 1970, d. h. im selben Jahr, in dem Codds Arbeit publik wurde, stellten Rudolf Bayer und Ed McCreight den B-Baum vor, eine Datenstruktur, die es ermöglicht, Relationen mit einer großen Anzahl von Tupel so auf einer Festplatte zu speichern, dass der lesende Zugriff auf Tupel sowie die Modifikation von Tupeln hocheffizient erfolgen kann.[11][12]
In den 1970er-Jahren begann auf Basis dieser beiden Arbeiten die Erfolgsgeschichte der Relationalen Datenbanken einschließlich der zugehörigen Sprache SQL. An Codds Arbeitsstätte, d. h. am IBM Research Laboratory in San Jose, wurden die Sprache SEQUEL sowie das experimentelle Datenbanksystem System R entwickelt. Später wurde SEQUEL in SQL umbenannt. Zu Beginn der 1980er-Jahre gab es für die Anfragesprache SQL die ersten kommerziellen relationalen Datenbanksysteme: Db2 von IBM und Oracle von Relational Software Inc.[13] Heute ist SQL aus der Welt der Datenbanken nicht mehr wegzudenken. Aber auch diverse weitere Sprachen, wie zunächst QBE[14] oder QUEL[15] und später Datalog[6], XQuery[16] oder SPARQL[5], basieren letztendlich auf der Idee Codds, Relationen zum Speichern von Daten einzusetzen.
Elemente einer Relationalen Algebra
Eine Relationale Algebra ist eine Algebra, deren Operationen Relationen auf Relationen abbilden. Abfragesprachen wie SQL, SPARQL, XQuery etc. liegt eine Relationale Algebra zugrunde. In derartigen Sprachen werden allerdings üblicherweise Tabellen oder noch komplexere Datenstrukturen wie beispielsweise JSON oder XML an Stelle von Relationen eingesetzt.
Unterschiede
Relation | Tabelle |
---|---|
duplikatfrei: Relationen sind Mengen, daher kommt kein Tupel zweimal vor. | Duplikate: Tabellen sind Listen, daher können gleiche Tupel mehrfach vorkommen. Allerdings gilt dies in SQL nur bei berechneten Tabellen, nicht aber bei gespeicherten Tabellen. |
ungeordnet: Relationen sind Mengen, daher sind die darin enthaltenen Tupel nicht geordnet. In einer Relationalen Algebra kann es keine Operation zum Sortieren von Relationen geben. |
geordnet: Tabellen sind (geordnete) Listen, daher ist die Reihenfolge der Tupel festgelegt. Allerdings kann man sich bei SQL-Befehlen nicht darauf verlassen, dass das Ergebnis in einer bestimmten Reihenfolge ausgegeben wird. In SQL gibt es daher eine spezielle ORDER-BY-Klausel, um eine bestimmte Reihenfolge zu erzwingen. |
Außerdem werden in SQL (Tabellen-)Zeilen (Rows) an Stelle von Tupeln verwendet. In Tabellenzeilen sind die einzelnen Spalten benannt und haben überdies eine Position.
Die klassische Tupeldefinition unterscheidet die verschiedenen Attribute anhand ihrer Position. Allerdings ist es nicht unüblich, diesen Positionen Namen zu geben. So wird bei einer Raumkoordinate die erste Position i. Allg. mit $ x $ bezeichnet, die zweite mit $ y $ und die dritte mit $ z $.
In Programmiersprachen heißen Tupel, deren Elemente über die Position bestimmt werden, Arrays oder Listen: [35, true, 'Hallo']
.
Tupel, deren Elemente mittels Identifikatoren unterschieden werden, heißen Records, Hashmaps/Hasharrays oder auch – z. B. in JavaScript – Objekte: {a: 35, b: true, c: 'Hallo'}
Ein Attribut kann als geordnetes Paar aufgefasst werden, bestehend aus Attributbezeichner und Attributwert. Abhängig von der Art der Attributbezeichnung unterscheidet man folgende Tupelarten:
Positionstupel | Tupel mit Attributnamen | Rows (Tabellenzeilen) |
---|---|---|
Die Attribute werden über ihre Position bestimmt, d. h., der Attributbezeichner ist eine natürliche Zahl. | Die Attribute werden über ihre Namen bestimmt, d. h., der Attributbezeichner ist eine Zeichenkette. | Die Attribute werden über ihren Namen oder ihre Position bestimmt, d. h., der Attributbezeichner ist eine Zeichenkette oder eine natürliche Zahl. |
t =
|
t =
|
t = Diese Art von Tupeln wird von üblichen Programmiersprachen nicht unterstützt. |
t[1] == 'y'
|
t['b'] == t.b == 'y'
|
t[1] == t['b'] == t.b == 'y'
|
In SQL werden benannte Attribute, d. h. Tupel mit Attributnamen verwendet. Allerdings ist es üblich, dass in Hostsprachen auf beide Arten auf ein Attribut zugegriffen werden kann. Beispielsweise stellt JDBC (Java Database Connectivity) die Methode getObject
zur Verfügung, die sowohl Integer- als auch Stringwerte als Attributbezeichner akzeptiert.[17]
Für Datenstrukturen wie JSON
oder XML
gelten analoge Aussagen:
Es gibt an Stelle von Relationen allgemeinere Container, deren Elemente geordnet sind und
Duplikate enthalten können. Außerdem gibt es Individuen, die als verallgemeinerte
Tupel aufgefasst werden können. Dabei kommen sowohl Positions- als auch benannte Attribute zum Einsatz.
Definitionen (Kowarschick (2018))
Tupelmengen und Relationenschemata
Positionstupel
Es seien $ n \in \mathbb{N}_0 $ und $ D_1, \ldots, D_n $ Domänen, d. h. nichtleere Mengen.
Die geordnete Liste $ R = [D_1, \ldots, D_n] $ heißt Relationenschema (für Positionstupel).
enthält alle Positionstupel der Art $ (v_1, \ldots, v_n) $, wobei $ v_i \in D_i $. (Es gilt also insbesondere $ T() = \{()\} $.)
Mittels $ t[i] $ greift man auf das $ i $-te Element $ v_i $ eines zugehörigen Tupels $ t = (v_1, \ldots, v_n) $ zu.
Eine Relation $ r := r_R := r(D_1,\dots, D_n) \subset T_R $ ist eine Relation mit Relationenschema $ R $, d. h. $ r_R $ enthält ausschließlich Positionstupel, die dem Relationenschema $ R $ genügen.
Attributtupel
Es seien $ a_1, \ldots, a_n $ ($ n \in \mathbb{N}_0 $) unterschiedliche Attributnamen ($ a_i \ne a_j $ für $ i \ne j $) und $ D_1, \ldots, D_n $ die zugehörige Domänen, d. h. nichtleere Mengen. Die Domäne $ D_i $ enthält alle Werte, die das Attribut $ a_i $ annehmen kann.
Ein Paar $ (a_i, D_i) = a_i : D_i $ heißt Attributdefinition. $ a_i $ ist der der Name des Attributs (Attributname), $ D_i $ die Domäne.
Die Menge $ R = \{(a_1, D_1), \ldots, (a_n, D_n)\} = \{a_1 : D_1, \ldots, a_n : D_n\} $ heißt Relationenschema (für Attributtupel).
Die Menge
enthält alle Attributtupel $ t = \{(a_1, v_1), \ldots, (a_n, v_n)\} = \{a_1 : v_1, \ldots, a_n : v_n\} $, wobei $ v_i \in D_i $. Man beachte, dass es bei einem derartigen Tupel nicht auf die Reihenfolge der Attribute ankommt, da ein Attributtupel eine Menge von Paaren ist.
Mittels $ t[a_i] = t.a_i = \bigcap\{v : (a_i, v) \in t \} $ greift man auf den Wert $ v_i $ des Attributs $ a_i $ eines zugehörigen Tupels $ t $ zu.
Eine Relation $ r := r_R := r(a_1: D_1, \ldots, a_n: D_n) $ ist eine Relation mit dem Relationenschema $ R $, d. h. $ r_R \subset T_R $ enthält Positionstupel, die dem Relationenschema $ R $ genügen.
Die Menge $ T(D_1, \ldots, D_n) $ kann mit der Menge $ T(1: D_1, \ldots, n: D_n) $ identifiziert werden (d. h., die zugehörigen Tupel können bijektiv aufeinander abgebieldet werden). Ebenso kann ein Relation $ r(D_1, \ldots, D_n) $ mit einer Relation $ r(1: D_1, \ldots, n:D_n) $ identifiziert werden.
Attributierte Positionstupel
Die Menge
enthalte alle attributierten Tupel deren Attribute zusätzlich mit einer Position versehen sind. Das heißt, sie enthält alle Tupel der Art $ (a_1/1:v_1, \ldots, a_n/n:v_n) $, wobei $ v_i \in D_i $.
Mittels $ t[a_i] $ oder auch $ t.a_i $ greift man auf den Wert $ v_i $ des Attributs $ a_i $ eines zugehörigen Tupels $ t $ zu. Und mittels $ t[i] $ greift man auf das $ i $-te Element von $ t $ zu.
In einer Relationalen Algebra ist eine Relation $ r $ i. Allg. eine Teilmenge einer Tupelmenge $ T(a_1/1: D_1, \ldots, a_n/n: D_n) $. Das heißt, jedes Tupel $ t \in r $ besteht aus einer geordneten Menge von Attributen, deren Werte vorgegebenen Domänen entstammen.
$ (a_1/1: D_1, \ldots, a_n/n: D_n) $ heißt das Schema der Relation $ r $.
$ \mathcal R $ sei die Menge aller Relationen. Die Potenzmenge einer der zuvor definierten Tupelmengen ist stets eine Teilmenge von $ \mathcal R $:
Jede Relation mit Schema $ T(a_1/1: D_1, \ldots, a_n/n: D_n) $ kann auch als Relation mit Schema $ T(a_1: D_1, \ldots, a_n: D_n) $ bzw. mit Schema $ T(D_1, \ldots, D_n) $ aufgefasst werden.
Relationale Algebra
Eine Algebra $ \mathfrak{R} = (\mathcal R, id, π, σ, \times, \div, \cup, \cap, \setminus) $ heißt Relationale Algebra wenn die Trägermenge $ R $ eine Menge von Relationen mit benannten Attributen ist.
- $ id: \mathcal R \rightarrow \mathcal R $ ist die so genannte Identitätsfunktion: Es gilt stets $ id(r) = r $
- $ π $ ist eine abzählbare Menge von (partiellen) Projektionsfunktionen $ π_{f_1 \,\text{as}\, a_1, \,\ldots, \,f_n \,\text{as}\, a_n}: \mathcal R \rightharpoonup \mathcal R $. Diese berechnen mit Hilfe der Funktionen $ f_i $ für jedes Tupel einer Relation $ r $ insgesamt $ n $ neue Attribue. Die neuen Attribute haben die Namen $ a_1 $ bis $ a_n $. Jeder dieser Funktionen werden die Attribute des jeweiligen Tupels als Argumente übergeben. Das heißt, eine Projektionsfunktion kann nur auf diejenigen Relationen angewendet werden, deren Attribute kompatibel mit den Projektionsfunktionen sind.
- $ σ $ ist eine abzählbare Menge von (partiellen) Selektionsfunktionen $ σ_b: \mathcal R \rightharpoonup \mathcal R $. Mit ihrer Hilfe werden aus einer Relation $ r $ diejenigen Tupel selektiert, die die Bedingung $ b $ erfüllen, d. h., für die Funktion $ b $ den Wert
true
liefert, wenn sie auf das jeweilige Tupel angewendet wird. Eine Selektionsfunktion kann nur auf diejenigen Relationen angewendet werden, deren Attribute kompatibel mit den Funktion $ b $ sind. - $ \times: \mathcal R, \mathcal R \rightharpoonup \mathcal R $ ist das kartesische Produkt, das zwei Relationen zu einer Relation verknüpft. Für jede mögliche Kombination von zwei Tupeln der Urbildrelationen ist die Konkatenation der beiden Tupel Element der Bildrelation. Das kartesische Produkt kann nur auf Relationenpaare angewendet werden, deren Attributnamen sich unterscheiden (da ein Tupel mit benannten Attributen keinen Attributnamen mehrfach enthalten kann).
- $ \div: \mathcal R, \mathcal R \rightharpoonup \mathcal R $ ist die Division. Im Prinzip ist dies die Umkehrfunktion des kartesischen Produktes.
- $ \cup: \mathcal R, \mathcal R \rightharpoonup \mathcal R $ ermittelt die Vereinigung zweier (strukturgleicher) Relationen.
- $ \cap: \mathcal R, R \rightharpoonup \mathcal R $ ermittelt den Durchschnitt zweier (strukturgleicher) Relationen.
- $ \setminus: \mathcal R, \mathcal R \rightharpoonup \mathcal R $ ermittelt die Differenz zweier (strukturgleicher) Relationen.
Relationale Operationen
Identität
Die Identitätsfunktion der Relationalen Algebra ist eine triviale Funktion: Sie bildet eine Relation (Tabelle) auf sich selbst ab:
$ id: \mathcal R \rightarrow \mathcal R $
$ id(r) = r $
Die Identiätsfunktion liefert als Ergebnisalso stets die Urbildrelation zurück. Das heißt, sie verändert eine Relation nicht.
Diese Funtion ist idempotent:
$ id(id(r)) = id(r) = r $
Die Identitätsfunktion ist eine der wenigen totalen Funktionen der Relationalen Algebra. Das heißt, sie kann auf jede beliebige Relation angewendet werden.
In SQL wird eine derartige Funktion benötigt, um den gesamten Inhalt einer Relation zu erfragen, da in jeder SQL-Anweisung zum Lesen von Dateninhalten mindestens eine relationale Operation enthalten sein muss.
In SQL 92[18]
wurde zu diesem Zweck der Befehl table
eingeführt, dessen einzige Aufgabe es ist, die ihm übergebene
Tabelle (Relation) vollständig auszugeben. Dieser Befehl ist jedoch nicht notwendig, da eine Projektion, die alle Attribute einer Relation unverändert zurück gibt,
ebenfalls als Identitätsfunktion verwendet werden kann (siehe nachfolgenden Abschnitt).
PostgreSQL beispielsweise unterstützt ihn dennoch.[19]
Beispiel
$ r $ | → | $ id(r) $ | ||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
→ |
|
SQL
TABLE r; -- seit SQL 92
SELECT a1, a2, a3, a4, a5 FROM r;
SELECT * FROM r;
Siehe auch Händler-Datenbank (SQL-Beispiel)/Identität
Projektion
Einfache Projektion
Es seien $ A = (a_1/1: D_1, \ldots, a_n/n:D_n) $ und $ B=(b_1/1: D'_1, \ldots, b_m/m:D'_m) $ zwei Schemata, mit $ \{b_1, \ldots, b_m\} \subset \{a_1, \ldots, a_n\} $ und $ D_i = D'_j $, falls $ a_i = b_j $
Die Projektionsfunktionen $ π $ wurden von Codd eingeführt, um Attribute einer Relation entfernen können. Eine Projektionsfunktion
$ π_{b_1, \ldots, b_m}: \mathscr{P} T(A) \rightarrow \mathscr{P}T(B) $
dient also dazu, bestimmte Spalten aus einer beliebigen (d. h. gespeicherten oder berechneten Tabelle) zu selektieren. Wenn $ r \in A $ eine Relation ist, dann ist $ π_{b_1, \ldots, b_m}(r) \in B $ diejenige Tabelle, die aus $ r $ entsteht, wenn man alle Spalten aus $ r $ entfernt, die nicht in {b_1, \ldots, b_m} enthalten sind. Dabei entstehende Duplikate müssen ebenfalls entfernt werden, sofern die Relationale Algebra – wie von Codd ursprünglich gefordert – mengenbasiert ist. In SQL werden nur gespeicherte Tabellen als duplikatifreie Mengen behandelt, berechnete Tabellen sind dagegen Multimengen, die Duplikate enthalten dürfen.
Außerdem führte Codd noch Permutationsfunktionen ein, um die Reihenfolge der Attribute zu ändern.[9][10] Der Begriff Permutation ist allerdings nur für Tupel mit Positionsattributen sinnvoll ([10,30]
und [30,10]
bezeichnen zwei verschiedene Punkte in einer Ebene). Für Tupel mit Attributnamen benötigt man dagegen keine Funktion, die Attribute vertauscht, da benannte Attribute keine Positionen besitzen ({x: 10, y: 30}
und {y: 30, x: 10}
bezeichnen denselben Punkt in einer Ebene). Hier muss eine „Permutationsfunktion“ Attributnamen umbenennen können. Die obige Definition beinhaltet bereits beide Arten von Permutation. Daher wir hier keine spezielle Permutationsfunktion benötigt.
Erweiterte Projektion
In der Zwischenzeit werden die Projektionsfunktionen allgemeiner definiert. Sie berechnen für jedes Tupel einer Relation aus dessen Attributwerten ein neues Tupel.
Es seien $ A = (a_1/1: D_1, \ldots, a_n/n:D_n) $ und $ B=(b_1/1: D'_1, \ldots, b_m/m:D'_m) $ zwei Schemata. Die Domänen brauchen nicht in irgendeine besondereren Beziehung zueinander zu stehen. Darüber hinaus gebe es $m$ Funktionen f_j: T(A) \rightarrow D'_j, die A-Tupel auf Elemente der zugehörigen Domäne $ D_j $ abbilden.
Die zugehörige Projektionsfunktion
$ π_{f_1 \,\text{as}\, b_1, \ldots, f_m \,\text{as}\, b_m}: \mathscr{P}T(A) \rightarrow \mathscr{P}T(B) $
bildet jedes A-Tupel einer zugehörigen Relation $ r $ auf ein B-Tupel ab, indem sie den Wert von $ b_j $ mittels $ f_j $ berechnet.
Die einfache Projektion ist ein Spezialfall dieser allgemeineren Definition, wenn man $ b_j $ sowohl als Attributnamen also auch als Funktion auffasst: $ b_j $ entspricht $ b_j \,\text{as}\, b_j $, wobei die Funktion $ b_j $ folgendermaßen definiert wird: $ b_j((a_1:v_1, \ldots, a_n:v_n)) = v_i $, falls der Attributename $ b_j $ gleich $ a_i $ ist.
Beachten Sie bitte: Die folgenden Beispiele funktionieren sowohl für Positionsattribute als auch für benannte Attribute als auch für Rows, bei denen Attribute sowohl eine Position als auch einen Namen haben.
Beispiele
$ r $ | → | $ π_{a_4, \,a_1}(r) $ | SQL | |||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
→ |
|
SELECT a4, a1 FROM r
|
Anmerkung: $ π_{a_4, \,a_1}(r) $ ist eine Abkürzung für $ π_{a_4 \rm{\,as\,} a_4, \,a_1 \rm{\,as\,} a_1}(r) $.
Attribute können auch berechnet und (um-)benannt werden. Duplikate, wie z. B. (a, g, 24), werden in der Relationalen Algebra automatisch entfernt. In SQL werden Duplikate nur dann entfernt, wenn man das Schlüsselwort „DISTINCT
“ angibt. SQL liegt eine so genannte Multimengen-Semantik zu Grunde.
$ r $ | → | $ π_{a_1, \,a_3, \,a_4+a_5 \rm{\,as\,} b_1}(r) $ | SQL | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
→ |
|
SELECT DISTINCT a4, a3, a4+a5 AS b1
|
Die Identitätsfunktion kann – wie es bereits weiter oben angesprochen wurde – mit Hilfe der Projektionsfunktion nachgebildet werden. Allerdings benötigt man für jede Relation eine spezielle Projektionsfunktion. In der Projektiosnliste müssen alle Attribute der zugehörigen Funktion genau einmal aufgeführt werden:
$ r $ | → | $ π_{a_1, \,a_2, \,a_3, \,a_4, \,a_5}(r) $ | SQL | |||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
→ |
|
SELECT a1, a2, a3, a4, a5 FROM r;
|
In SQL kann man abkürzend den Stern „*
“ verwenden. Dieser bezeichnet alle Attribute der aktuellen Relation.
Mit r.*
werden in SQL alle Attribute der Relation r
bezeichnet. Für das obige Beispiel kann man in der
Relationalen Algebra analog folgenden Abkürzungen definieren:
$ r = π_{a_1, \,a_2, \,a_3, \,a_4, \,a_5}(r) = π_{r.*}(r) = π_{*}(r) = id(r) $
Mit dem Stern-Operator man also eine alternative Definition der Identitätsfunktion mit Hilfe des Projektionsoperators angeben, die ohne die Attributnamen der jeweiligen Relation auskommt. (In SQL ist die Verwendung des Sternoperator allerdings verpönt, da sich die Attribute einer Tabelle im Laufe der Zeit ändern können (Schemaevolution) und sich damit die Bedeutung des Sterns ändert. Das heißt, Anfragen, die einen *
enthalten, können plötzlich weniger, mehr oder andere Spalten im Ergebnis liefern.)
Siehe auch Händler-Datenbank (SQL-Beispiel)/Projektion
Selektion
Eine Selektionsfunktion entfernt Zeilen (= Tupel) aus einer Tabelle.
$ r $ | → | $ σ_{a_1= \tt{'a'}}(r) $ | SQL | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
→ |
|
SELECT *
|
$ r $ | → | $ σ_{a_1 = \tt{'a'} \,\wedge\, a_5<21}(r) $ | SQL | |||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
→ |
|
SELECT *
|
Siehe auch Händler-Datenbank (SQL-Beispiel)/Selektion
Kartesisches Produkt
Das Kartesische Produkt verknüpft alle möglichen Tupelpaare zweier Relationen zu jeweils einem Tupel, das alle Attribute beider Tupel enthält.
$ r $ | $ \times $ | $ s $ | → | $ r $ | SQL | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
$ \times $ |
|
→ |
|
SELECT *
|
Siehe auch Händler-Datenbank (SQL-Beispiel)/Kartesisches Produkt
Join
Ein Join ist formal nichts weiter, als ein Kartesisches Produkt gefolgt von einer Selektion.
Siehe auch Händler-Datenbank (SQL-Beispiel)/Join
TO BE DONE
- $ ⨝ $, $ ⟕ $, $ ⟖ $, $ ⟗ $, $ \triangle $
Quellen
- ↑ Ullman (1988): Jeffrey D. Ullman; Principles of Database and Knowledge-Base Systems – Volume I: Classical Database Systems; Verlag: Computer Science Press; Adresse: New York, Oxford; ISBN: 0-7167-8158-1; Web-Link; 1988; Quellengüte: 5 (Buch), Seite=53
- ↑ Ullman (1988): Jeffrey D. Ullman; Principles of Database and Knowledge-Base Systems – Volume I: Classical Database Systems; Verlag: Computer Science Press; Adresse: New York, Oxford; ISBN: 0-7167-8158-1; Web-Link; 1988; Quellengüte: 5 (Buch), Seite=210
- ↑ , Seiten 9–16
- ↑ 5,0 5,1
- ↑ 6,0 6,1
- ↑ Ullman (1989): Jeffrey D. Ullman; Principles of Database and Knowledge-Base Systems – Volume II: The New Technologies; Verlag: Computer Science Press; Adresse: New York, Oxford; ISBN: 0-7167-8069-O, 0-7167-8182-X; Web-Link; 1989; Quellengüte: 5 (Buch), Chapter 11
- ↑ 8,0 8,1
- ↑ 9,0 9,1 9,2 9,3 Codd (1969): Edgar Frank Codd; Derivability, Redundancy and Consistency of Relations Stored in Large Data Banks; in: ACM SIGMOD Record; Band: 38; Nummer: 1; Seite(n): 17–36; Verlag: Association for Computing Machinery; Adresse: New York; Web-Link; 2009; Quellengüte: 5 (Artikel)
- ↑ 10,0 10,1 10,2 Codd (1970): Edgar Frank Codd; A Relational Model of Data for Large Shared Data Banks; in: Communications of the ACM; Band: 13; Nummer: 6; Seite(n): 377-387; Verlag: Association for Computing Machinery; Adresse: New York; Web-Link; 1970; Quellengüte: 5 (Artikel)
- ↑
- ↑ Bayer, McCreight (1972): Rudolf Bayer und Edward M. McCreight; Organization and Maintenance of Large Ordered Indexes; in: Acta Informatica; Band: 1; Nummer: 3; Seite(n): 173-189; Verlag: Springer-Verlag; Web-Link; 1972; Quellengüte: 5 (Artikel)
- ↑
- ↑ Ullman (1988): Jeffrey D. Ullman; Principles of Database and Knowledge-Base Systems – Volume I: Classical Database Systems; Verlag: Computer Science Press; Adresse: New York, Oxford; ISBN: 0-7167-8158-1; Web-Link; 1988; Quellengüte: 5 (Buch), Seiten 195–210
- ↑ Ullman (1988): Jeffrey D. Ullman; Principles of Database and Knowledge-Base Systems – Volume I: Classical Database Systems; Verlag: Computer Science Press; Adresse: New York, Oxford; ISBN: 0-7167-8158-1; Web-Link; 1988; Quellengüte: 5 (Buch), Seiten 185–195
- ↑
- ↑ Taylor (2003): Art Taylor; JDBC – Database Programming with J2EE; Auflage: 5; Verlag: Prentice Hall; Adresse: Upper Saddle River, New York, USA; ISBN: 0-13-045323-4; 2003; Quellengüte: 5 (Buch), Seite 332–333
- ↑ Date, Darwen (1993): Christopher J. Date und Hugh Darwen; A Guide to the SQL Standard – A user's guid to the standard relational language SQL; Auflage: 3; Verlag: Addison-Wesley; Adresse: Reading, Massachusetts, USA; 1993; Quellengüte: 5 (Buch)
- ↑ https://www.postgresql.org/docs/current/static/sql-select.html PostgreSQL: Select
- Ullman (1988): Jeffrey D. Ullman; Principles of Database and Knowledge-Base Systems – Volume I: Classical Database Systems; Verlag: Computer Science Press; Adresse: New York, Oxford; ISBN: 0-7167-8158-1; Web-Link; 1988; Quellengüte: 5 (Buch)
- Ullman (1989): Jeffrey D. Ullman; Principles of Database and Knowledge-Base Systems – Volume II: The New Technologies; Verlag: Computer Science Press; Adresse: New York, Oxford; ISBN: 0-7167-8069-O, 0-7167-8182-X; Web-Link; 1989; Quellengüte: 5 (Buch)
- Garcia-Molina, Ullman, Widom (2002): Hector Garcia-Molina, Jeffrey D. Ullman und Jennifer Widom; Database Systems: The Complete Book; Verlag: Prentice Hall; Adresse: New Jersey, Upper Saddle River; ISBN: 0-13-031995-3; Web-Link; 2002; Quellengüte: 5 (Buch)
- Elmasri, Navathe (2011): Ramez Elmasri und Shamkant B. Navathe; Fundamentals of Database Systems; Auflage: 3; Verlag: Pearson Studium; ISBN: 978-0-136-08620-8; 2011; Quellengüte: 5 (Buch)