Relationale Datenbanken
Willemers Informatik-Ecke

Datenbank

Der Begriff Datenbank wird häufig für verschiedene Dinge bezeichnet, die sich eigentlich klar unterscheiden: Ein DBMS ermöglicht ...

Relationen

Fast alle heute eingesetzten Datenbanken arbeiten relational. Das bedeutet, dass ihre Daten in Tabellen gehalten werden. Dieses Datenmodell wurde etwa 1970 von Edgar F. Codd vorgestellt.

Codd bezeichnet Datenbanken als "minimal relational", wenn sie folgende Bedingungen erfüllen.

  1. Die Informationen werden einheitlich in Form von Tabellen repräsentiert.
  2. Der Anwender sieht keine Verweisstrukturen zwischen den Tabellen.
  3. Es gibt mindestens die Operation der Selektion, der Projektion und des JOIN definiert.

Tabellen

Eine Zeile in einer Tabelle wird als Tupel, Row oder auch als Record bezeichnet.

Die Spalte einer Tabelle werden als Attribut, Column oder Field bezeichnet.

Eine Tabelle kann sowohl ein Entity darstellen als auch die Beziehung von Entities ausdrücken. So kann es eine Tabelle für Kunden und eine für Artikel geben. Beides sind Entities. Der Kauf eines Artikels kann in einer Tabelle abgelegt werden, die neben dem Verweis auf den Kunden und den Artikel auch weitere Atribute über den Kauf enthalten kann, wie etwa den Preis und das Datum.

Entity Relationship

Zum Design einer Datenbank dient die Bildung eines Datenmodells. Das populärste Werkzeug ist das Entitiy Relationship Model.

Ein einfacher Ansatz für den konzeptionellen Entwurf ist, die Formulierung von Sätzen, die die Anwendung der Datenbank beschreiben. Wie etwa: "Der Kunde kauft Artikel".

In diesem Fall ergeben sich die Entities meist aus den Substantiven und die Relation aus den Verben.

Die Attribute einer Tabelle lassen sich durch das Wort haben leicht finden. "Artikel haben einen Preis und eine Bezeichnung".

Beispiel

Soll der Verkauf von Artikeln abgebildet werden, hat man zwei Entitäten: Kunden und Artikel. Zwischen beiden gibt es eine Beziehung (Relation): der Kauf. Damit haben wir drei Tabellen: Kunde, Artikel und Kauf. Die Tabelle Kauf enthält minimal die Fremdschlüssel von Kunde und Artikel.

Notationen

Der Informatiker Peter Chen stellte ein Diagramm zur Darstellung von Datenbankschemata vor. Insbesondere beim ORM (Object Relationship Mapping) wird auch UML verwendet.

Selektion

Eine Selektion ist ein zeilenweises Ausfiltern der Entities. Typischerweise wird dies in SQL durch die WHERE-Klausel erreicht.

Projektion

Eine Projektion entsteht durch das Ausfiltern der Spalten. Dadurch entstehende Duplikate werden entfernt, da die Projektion selbst wieder eine Relation bildet.

View

Eine View ist eine Kombination aus Selektion und Projektion, die wie eine Tabelle gelesen, aber nicht geschrieben werden kann, da sie nicht als Tabelle gespeichert wird.

Wird eine View auf eine einzelne Tabelle gesetzt, kann diese also zum Lesen freigegeben werden, ohne dass der Benutzer ein Schreibrecht erlangt.

Die Schlüsselfrage

Schlüssel und funktionale Abhängigkeit

Um jede Zeile innerhalb der Tabelle direkt ansprechen zu können, wird ein Schlüssel definiert. Der Schlüssel einer Tabelle identifiziert also eindeutig eine Zeile der Tabelle. Man spricht auch davon, dass die Felder, die nicht im Schlüssel vorkommen, von diesem funktional abhängig sind.

Ein Schlüssel kann aus mehreren Feldern zusammengesetzt sein. So ist der Name einer Person in der Regel für eine Eindeutigkeit nicht ausreichend. Erst wenn Geburtstag und Geburtsort hinzukommt, wird der Schlüssel eindeutig.

Solch zusammengesetzte Schlüssel erweisen sich in der Praxis als unhandlich. Darum werden gern Zahlenfelder für die Tabelle definiert, die für jede Zeile eindeutig sind, beispielsweise Artikelnummern.

Ein solcher Schlüssel wird auch als Primärschlüssel bezeichnet.

Daneben kann es mehrere Sekundärschlüssel geben, die nicht zwingend eindeutig sein müssen. Sie beschleunigen vor allem die Suche nach Einträgen. Darum kann man sie auch als Suchschlüssel bezeichnen.

Fremdschlüssel und die referentielle Integrität

Eine Tabelle verweist auf eine andere, indem sie deren Schlüssel in einer Spalte speichert. So enthält eine Bestellung beispielsweise die Kundennummer des Bestellers. Diese ist dann beispielsweise der Primärschlüssel der Tabelle Kunde.

Ein solcher Verweis wird als Fremdschlüssel bezeichnet. Die referentielle Integrität fordert, dass für jeden Fremdschlüssel der Datensatz existiert, der referenziert wird. Das bedeutet, dass die Datenbank verhindern muss, dass ein Satz gelöscht wird, auf den noch ein Fremdschlüssel verweist.

Constraints

Der Datenbank können Regeln auferlegt werden. Beide Regeln sind bei Primärschlüsseln erforderlich.

Der Eintrag FOREIGN KEY bewirkt, dass eine Zeile auf die verwiesen wird, nicht gelöscht werden kann.

Normalisierung

Die Normalisierung dient in erster Linie des Abbaus der Redundanzen. J.W.Schmidt (S.38) definiert:
"Relationen, deren sämtliche Nicht-Schlüsselattribute funktional vom Schlüssel abhängen und weitere funtionale Abhängigkeiten nicht besitzen, nennt man normalisiert."

Es ergeben sich die Folgerungen:

Eine Tabelle sollte einen Primärschlüssel haben
Eine Tabelle sollte nur Daten für einen Typ einer Entität aufnehmen
Eine Tabelle sollte Spalten vermeiden, deren Elemente leer sein können
Eine Tabelle sollte keine wiederholenden Werte haben.

Erste Normalform

Die Attributwerte sind atomar. Das bedeutet konkret, dass jede Information einer Tabelle eine eigene Spalte erhält. Vorname und Name (PLZ und Ort) erhalten jeweils ein eigenes Feld

Zweite Normalform

Die Tabelle liegt in der ersten Normalform vor. Zusätzlich gilt: Jedes Nichtschlüsselattribut ist von jedem Schlüsselattribut voll funktional abhängig.

Dritte Normalform

Die Tabelle liegt in der zweiten Normalform vor. Zusätzlich gilt: Kein Nichtschlüsselattribut hängt von einem Schlüssel transitiv ab. Transitiv abhängige Spalten werden in eine separate Tabelle ausgelagert.

Kardinalität

Die Sprache SQL

Um eine Datenbank zu verändern, wird häufig ein Interpreter verwendet, der dem Anwender eine Sprache zur Verfügung stellt. Inzwischen hat sich SQL zum Standard entwickelt. Die Sprache ist nicht case-sensitive, sie ignoriert also Groß- und Kleinschreibung.

Die Kommandos können durch die datenbankeigene Kommnadoeingabe übergeben werden. Für die Anbindung der Datenbank an Anwendungen haben sich inzwischen ODBC (Microsoft) und JDBC (Java) entwickelt, die SQL-Kommandos an die Datenbank senden.

Die SQL-Befehle müssen in den Kommandointerpretern verschiedener DBMS mit einem Semikolon abgeschlossen werden, bevor sie ausgeführt werden. Das Semikolon gehört aber nicht zum Sprachumfang und wird darum beispielsweise bei JDBC nicht angegeben.

Die Befehle werden nach in zwei Kategorien unterteilt. So wird das Anlegen und Administrieren der Datenbank durch die DDL und die Auswertung und Pflege der eigentlichen Daten durch die DML erreicht.

Data Definition Language (DDL)

Mit der DDL werden die Tabellen angelegt, gelöscht oder ihre Struktur verändert.

Die SQL-Kommandos CREATE, ALTER und DROP werden für die Erstellung, Änderung und das Löschen von Datenbanken, Tabellen, Benutzern oder Rechten verwendet.

Datenbanken verwalten

Im ersten Schritt wird mit CREATE DATABASE eine Datenbank angelegt, die als Container für Tabellen dient. Dem Befehl muss ein Bezeichner folgen.

Mit DROP DATABASE gefolgt vom Bezeichner wird die Datenbank (und alle sie enthaltenen Tabellen) wieder gelöscht.

Tabellen verwalten

Eine Tabelle wird mit dem Befehl CREATE TABLE gefolgt vom Bezeichner der Tabelle angelegt. Die Struktur der Tabelle wird in einem folgenden Klammerpaar ausgeführt.
CREATE TABLE artikel (
   artikel_id INT NOT NULL PRIMARY KEY,
   bezeichnung VARCHAR,
   preis DEC(8,2)
)

Data Manipulation Language (DML)

Mit der DML werden Daten in die Tabellen geschrieben, gelöscht, verändert oder die Tabellen ausgewertet.

Dazu gibt es vor allem vier Operationen:

Transaktionen

Mehrere Datenbankveränderungen können zusammengehören. So wird beim Kauf einer Ware Wird nur einer der beiden Schritte ausgeführt, kommt es zu einer Schieflage der Datenbank. Damit beide Aktionen ausgeführt werden, werden sie zu einer Transaktion zusammengefasst. Eine Transaktion wird vollständig oder gar nicht ausgeführt. Um dies zu erreichen, definiert man eine atomare Einheit aus Start, Rollback und Commit.

Das ACID-Prinzip besagt, dass die Transaktion folgende Eigenschaften erfüllt:

Atomic
Die Transaktion wird vollständig oder gar nicht ausgeführt.
Consistency
War die Datenbank vor der Transaktion konsistent, muss sie es auch nach der Transaktion sein.
Isolation
Parallel laufende Transaktionen dürfen sich gegenseitig nicht stören.
Durability
Die Transaktionsergebnisse müssen dauerhaft sein.

Pessimistisch/Sperren

Um sicherzustellen, dass eine Transaktion isoliert laufen kann, gibt es verschiedene Ansätze.

Die pessimistische Annahme geht davon aus, dass es passieren kann, dass eine parallele Aktivität die Ressourcen der Transaktion stört. Damit das nicht passiert, werden alle Ressourcen gesperrt.

Sperren führen immer zum Risiko eines Deadlocks. Um Deadlocks zu verhindern, könnte die Parallelität der Transaktionen aufgehoben werden. Oder aber man versucht einen Deadlock zu erkennen, indem man einen Timeout setzt.

Optimistisch

Der optimistische Ansatz geht davon aus, dass vermutlich keine Konflikte entstehen. Dabei wird auf einer Kopie der Daten gearbeitet. Anschließend wird geprüft, ob es in der Zeit der Transaktion einen Zugriff auf die Daten gegeben hat. Ist das der Fall, wird ein Rollback der Transaktion durchgeführt.

Joins

Ein Join ist eine Zusammenfassung zweier Tabellen. Die Spalten der Ergebnistabelle ergibt sich aus der Art des Joins.

Kartesisches Produkt (CROSS JOIN)

Das kartesische Produkt ist ein Join, der nicht beschränkt ist. Etwas lässig formuliert, könnte man sagen: Jeder gegen jeden. In Bezug auf die Relationale Algebra entspricht dies einem kartesischen Produkt.

Wenn Sie eine Tabelle KARTENWERT mit den Kartenwerten 7, 8, 9, 10, B, D, K, A füllen und eine Tabelle KARTENFARBE mit Kreuz, Pik, Herz, Karo füllen, würde das kartesische Produkt ein Skatblatt mit 32 Karten ergeben, in dem alle Kartenwerte mit allen Kartenfarben kombiniert werden.

SELECT * FROM kunde, betreuer
Es entsteht eine Tabelle, in der jeder Kunde mit jedem Betreuer kombiniert wird.

Im SQL-Standard SQL-92 kann das Schlüsselwort CROSS JOIN eingefügt werden, um die Eigenschaft als Kreuz-Relation besonders zu betonen.

SELECT * FROM kunde CROSS JOIN betreuer

Inner Join

Ein kartesisches Produkt wird eher selten benötigt. Meist haben die Tabellen einen Verknüpfungspunkt. Der Mitarbeiter gehört zu einer Abteilung. Der Kunde hat jeweils einen Betreuer, der ihm zugewiesen ist. Diese Verbindung erfolgt meist über die Gleichheit der Werte in einer Spalte.

Equi-Join

Der Equi-Join trägt schon im Namen, dass die Verbindung zweier Tabellen durch die Gleichheitsbedingung der Felder herbeigeführt.

Beispielsweise will man eine Liste aller Kunden mit dem Namen ihrer Betreuer. Die Tabelle BETREUER enthält als Primärschlüssel ID. Die Tabelle KUNDE enthält eine Spalte BETREUERID.

SELECT kunde.name, betreuer.name 
  FROM kunde, betreuer 
  WHERE betreuer.id=kunde.betreuerid;
Alternativ kann der Befehl auch seine JOIN-Eigenschaft folgendermaßen dokumentieren:
SELECT kunde.name, betreuer.name 
  FROM kunde JOIN betreuer 
  ON betreuer.id=kunde.betreuerid;

Natural Join

Der Natural Join kann verwendet werden, wenn die Namen der verbindenden Spalten gleich benannt sind. So würde der Natural Join bei Betreuer und Kunde funktionieren, wenn die ID in der Tabelle Betreuer betreuerid wie in der Tabelle Kunde hieße. Um Verwechslungen auszuschließen, müssten dann das Feld name bei betreuer und kunde unterschiedlich heißen.
SELECT kunde.kname, betreuer.bname
  FROM kunde NATURAL JOIN betreuer
Man kann allerdings auch explizit die Spalten mit der Übereinstimmung festmachen, indem man das Schlüsselwort USING verwendet. Dann dürfen die Namen in beiden Tabellen auch wieder gleich lauten.
SELECT kunde.name, betreuer.name
  FROM kunde JOIN betreuer USING (betreuerid)

Outer Join

Ein Outer Join zeigt auch Kunden an, die keinen Betreuer haben bzw. Betreuer, die keine Kunden haben. Fehlende Werte werden durch NULL aufgefüllt.

Der Left Outer Join geht vom Kunden aus und füllt die Betreuernamen mit NULL auf, wenn der Kunde keinen Betreuer hat.

SELECT kunde.name, betreuer.name
  FROM kunde LEFT OUTER JOIN betreuer USING (betreuerid)
Der Right Outer Join zeigt alle Betreuer an und füllt die zugehörigen Kundennamen mit NULL auf, wenn der Betreuer noch keine Kunden hat.
SELECT kunde.name, betreuer.name
  FROM kunde RIGHT OUTER JOIN betreuer USING (betreuerid)

Literatur

P.C.Lockemann u. J.W.Schmidt (Hrsg)
Datenbank-Handbuch, Springer, 1987. Aktuellere Auflage von 2012
K. Dittrich: Datenbanksysteme. in Informatik-Handbuch. Carl Hanser, München Wien. S. 750ff.