Datenbanksysteme
Große Datenmengen, wie sie beispielsweise in einem Social Network oder Online-Shop anfallen, werden üblicherweise als Datenbanksystem (database system, DBS) verwaltet. Dazu benötigt man ein Programm, das man als Datenbankmanagementsystem (database management system, DBMS) bezeichnet. Ein DBMS kann eine oder mehrere Datenbanken betreiben. Eine Datenbank (database, DB) wiederum besteht aus dem Schema (schema), das die Struktur der zu speichernden Daten beschreibt, und den eigentlichen Daten (data).
Es gibt viele verschiedene Arten von Datenbanksysteme. Wir werden hier zunächst nur relationale Datenbanksysteme thematisieren.
Die Structured Query Language (SQL) ist eine standardisierte Sprache zum Bedienen von DBMS. Sie ist heute sehr weit verbreitet und wird von den meisten DBMS unterstützt. Die zahlreichen SQL-Befehle kann man grob wie folgt einteilen:
- Data Definition Language (DDL) -- Festlegen des Datenbankschemas
- Data Manipulation Language (DML) -- Arbeiten mit dem Datenbestand
- Data Query Language (DQL) -- Abfragen (SELECT)
- Befehle zur Pflege des Datenbestandes (INSERT, UPDATE, DELETE)
- Transaction Control Language (TCL) -- Arbeiten mit Transaktionen
- Data Control Language (DCL) -- Festlegen von Zugriffsrechten
Inhaltsverzeichnis
Festlegen des Datenbankschemas
Definieren von Spalten
Beispiel: Web-Forum
CREATE TABLE Categories ( CategoryID INTEGER, Title CHAR(255), Description VARCHAR(4096) );
CREATE TABLE Users ( UserID INTEGER, LoginName CHAR(64), PasswdHash CHAR(255), EMailAddr CHAR(255), LastName CHAR(255), FirstName CHAR(255), BirthDate DATE );
CREATE TABLE Posts ( PostID INTEGER, Category INTEGER, Author INTEGER, Parent INTEGER, Title VARCHAR(512), Content TEXT, CreatedOn TIMESTAMP, EditedOn TIMESTAMP );
Pflichtfelder
CREATE TABLE Categories ( CategoryID INTEGER NOT NULL, Title CHAR(255) NOT NULL, Description VARCHAR(4096) NULL );
CREATE TABLE Users ( UserID INTEGER NOT NULL, LoginName CHAR(64) NOT NULL, PasswdHash CHAR(255) NOT NULL, EMailAddr CHAR(255) NOT NULL, LastName CHAR(255) NULL, FirstName CHAR(255) NULL, BirthDate DATE NULL );
CREATE TABLE Posts ( PostID INTEGER NOT NULL, Category INTEGER NOT NULL, Author INTEGER NULL, Parent INTEGER NULL, Title VARCHAR(512) NOT NULL, Content TEXT NOT NULL, CreatedOn TIMESTAMP NOT NULL, EditedOn TIMESTAMP NULL );
Primärschlüssel
CREATE TABLE Categories ( CategoryID INTEGER NOT NULL, Title CHAR(255) NOT NULL, Description VARCHAR(4096) NULL, PRIMARY KEY (CategoryID) );
CREATE TABLE Users ( UserID INTEGER NOT NULL, LoginName CHAR(64) NOT NULL, PasswdHash CHAR(255) NOT NULL, EMailAddr CHAR(255) NOT NULL, LastName CHAR(255) NULL, FirstName CHAR(255) NULL, BirthDate DATE NULL, PRIMARY KEY (UserID) );
CREATE TABLE Posts ( PostID INTEGER NOT NULL, Author INTEGER NULL, Category INTEGER NOT NULL, Title VARCHAR(512) NOT NULL, Content TEXT NOT NULL, CreatedOn TIMESTAMP NOT NULL, EditedOn TIMESTAMP NULL, PRIMARY KEY (PostID) );
Eindeutige Werte
CREATE TABLE Categories ( CategoryID INTEGER NOT NULL, Title CHAR(255) NOT NULL, Description VARCHAR(4096) NULL, PRIMARY KEY (CategoryID), UNIQUE (Title) );
CREATE TABLE Users ( UserID INTEGER NOT NULL, LoginName CHAR(64) NOT NULL, PasswdHash CHAR(255) NOT NULL, EMailAddr CHAR(255) NOT NULL, LastName CHAR(255) NULL, FirstName CHAR(255) NULL, BirthDate DATE NULL, PRIMARY KEY (UserID), UNIQUE (LoginName), UNIQUE (EMailAddr) );
Fremdschlüssel
Häufig beziehen sich die Daten in einer Tabelle auf Daten in einer anderen Tabelle. Um die referenzielle Integrität der Daten bei derartigen Verweisen unter allen Umständen sicherstellen zu können, bietet SQL die Möglichkeit, sogenannte Fremdschlüssel zu definieren. Dabei muss sich ein FOREIGN KEY immer auf einen PRIMARY KEY oder ein UNIQUE-Constraint in der anderen Tabelle beziehen. Fremdschlüssel müssen in der untergeordneten Tabelle eingetragen werden.
Eins-zu-eins-Beziehungen sowie Eins-zu-viele-Beziehungen im Datenmodell können mit Hilfe von Fremdschlüsseln direkt in SQL implementiert werden. Für Viele-zu-viele-Beziehungen wird eine separate Tabelle benötigt, in der die Paare gespeichert werden. In SQL kann man bei der Definition eines Fremdschlüssels mittels der Klauseln ON UPDATE und ON DELETE angeben, was mit den Zeilen in der untergeordneten Tabelle passieren soll, wenn ein Primärschlüssel in der übergeordneten Tabelle geändert oder gelöscht wird. Dabei gibt es jeweils folgende Möglichkeiten:
- NO ACTION bedeutet, wie der Name schon sagt, dass beim Ändern oder Löschen eines Primärschlüssels keine besondere Maßnahme ergriffen wird. Falls dieser Schlüssel in der untergeordneten Tabelle vorkommt, dann schlägt der entsprechende SQL-Befehl fehl, falls nach Ausführung aller Trigger die referenzielle Integrität verletzt wäre.
- RESTRICT lässt das Ändern oder Löschen eines Primärschlüssels, der bereits von einem Fremdschlüssel referenziert wird, gar nicht zu, auch dann nicht, wenn die referenzielle Integrität durch einen oder mehrere Trigger wiederhergestellt würde.
- SET NULL gibt an, dass alle Fremdschlüssel auf NULL gesetzt werden sollen, wenn der entsprechende Primärschlüssel geändert oder gelöscht wird. Diese Option kann natürlich nur verwendet werden, wenn in der oder den Fremdschlüssel-Spalten NULL-Werte erlaubt sind.
- SET DEFAULT bewirkt, dass die Werte in der oder den Fremdschlüssel-Spalten auf ihre Default-Werte zurückgesetzt werden, wenn der entsprechende Primärschlüssel geändert oder gelöscht wird.
- CASCADE sorgt dafür, dass beim Ändern eines Primärschlüssels alle betroffenen Fremdschlüssel in oder untergeordneten Tabelle ebenfalls geändert werden. Beim Löschen einer Zeile in der übergeordneten Tabelle werden alle Zeilen in der untergeordneten
Tabelle, die per Fremdschlüssel auf diese Zeile verweisen, ebenfalls gelöscht. Leider sind nicht alle Optionen in allen DBMS (korrekt) implementiert. Im Zweifel kommt man nicht umhin, die Dokumentation zu bemühen, um sich Klarheit darüber zu verschaffen, welche Möglichkeiten beim Definieren von Fremdschlüsseln vorhanden sind.
Bei der Auswahl geeigneter Optionen kann man sich an folgenden Faustregeln orientieren: (1) Für natürliche Primärschlüssel wählt man bei allen Fremdschlüsseln, die sich darauf beziehen, ON UPDATE CASCADE, um die referenzielle Integrität auch beim Ändern von Daten zu wahren. Bei künstlichen Primärschlüsseln kann man ON UPDATE RESTRICT verwenden, da es keinen Grund gibt, diese jemals ändern zu wollen. Sollte man doch in diese Versuchung kommen, dann handelt es sich vermutlich gar nicht wirklich um künstliche Schlüssel, sondern sie beinhalten doch auf subtile Weise eine Semantik. (2) Bei einer Komposition im Datenmodell verwendet man ON DELETE CASCADE, bei einer Aggregation je nach Anwendungskontext eine der anderen Optionen.
CREATE TABLE Posts ( PostID INTEGER NOT NULL, Category INTEGER NOT NULL, Author INTEGER NULL, Parent INTEGER NULL, Title VARCHAR(512) NOT NULL, Content TEXT NOT NULL, CreatedOn TIMESTAMP NOT NULL, EditedOn TIMESTAMP NULL, PRIMARY KEY (PostID), FOREIGN KEY (Category) REFERENCES Categories (CategoryID) ON UPDATE RESTRICT ON DELETE CASCADE, FOREIGN KEY (Author) REFERENCES Users (UserID) ON UPDATE RESTRICT ON DELETE SET NULL, FOREIGN KEY (Parent) REFERENCES Posts (PostID) ON UPDATE RESTRICT ON DELETE CASCADE );
Das Beispiel zeigt, dass sich ein Fremdschlüssel auch auf einen Schlüssel in derselben Tabelle beziehen kann. Auf diese Weise lassen sich hierarchische Strukturen (Baumstrukturen) in SQL mühelos abbilden.
Weitere Bedingungen
CREATE TABLE Posts ( PostID INTEGER NOT NULL, Author INTEGER NULL, Category INTEGER NOT NULL, Title VARCHAR(512) NOT NULL, Content TEXT NOT NULL, CreatedOn TIMESTAMP NOT NULL, EditedOn TIMESTAMP NULL, PRIMARY KEY (PostID), FOREIGN KEY (Author) REFERENCES Users (UserID) ON UPDATE RESTRICT ON DELETE SET NULL, FOREIGN KEY (Category) REFERENCES Categories (CategoryID) ON UPDATE RESTRICT ON DELETE CASCADE, CHECK (CreatedOn < EditedOn) );