Datenbanken, Teil 3: Tabellen erstellen mit SQL

Im zweiten Teil der Serie über Datenbanken, der zugegebenermaßen schon etwas zurück liegt, hatte ich versprochen, im folgenden Teil der Serie zu zeigen, wie man in der Praxis mit SQL Tabellen erstellt. Dieses Versprechen will ich nun hiermit einlösen. In der ersten Staffel unseres Podcasts haben uns in der Zwischenzeit allerdings auch schon mit SQL beschäftigt.

SQL ist eine weit verbreitete Sprache für relationale Datenbankmanagementsysteme und umfasst, wie im ersten Teil schon erwähnt, sowohl eine Abfragesprache (Query Language) wie auch Sprachen zum Einfügen und Löschen von Daten (Data Manipulation Langauge) und zum Anlegen eines Datenbankschemas (Data Definition Language). SQL wird von vielen aktuellen relationalen Datenbankmanagementsystemen (DBMS) verstanden. Ein weit verbreitetes und kostenloses DBMS ist MySQL. Die Codebeispiele in diesem und den folgenden Teilen beziehen sich, sofern nichts anderes angegeben ist, auf MySQL. Da SQL aber weitgehend standardisiert ist, sollten sie auch in anderen DBMS funktionieren.

Erstellen einer Datenbank

Ein DBMS kann üblicherweise mehrere Datenbanken gleichzeitig verwalten. Deshalb ist es zunächst einmal nötig, bevor Tabellen erstellt werden können, eine Datenbank zu erstellen. Dem DBMS muss man dann mitzuteilen, dass diese Datenbank ab sofort benutzt werden soll. SQL-Anweisung werden übrigens stets mit einem Semikolon abgeschlossen.

CREATE DATABASE meineDatenbank;

USE meineDatenbank;

Anlegen von Tabellen

SQL ist im allgemeinen eine recht geschwätzige Sprache. Schlüsselworte in SQL lesen sich oftmals wie ganz normales Englisch. „Lege eine Tabelle an“ heißt auf Englisch „create table“, und genau das ist der SQL-Befehl dafür. Es muss noch angegeben werden, welche Spalten die Tabelle haben soll und welche Datentypen diese Spalten haben, also welche Art von Daten die Spalte aufnehmen soll. Die wichtigsten Datentypen sind:

INTEGERGanze Zahlen
NUMERIC(n,m) oder DECIMAL(n,m)Dezimalzahlen mit Längenangaben
n steht für Anzahl der Stellen insgesamt
m für die Anzahl der Nachkommastellen
FLOAT(n), DOUBLE, REALGleitkommazahlen
Es ist meistens keine gute Idee, diesen
Datentyp zu verwenden, da die Zahlen intern als binäre Gleitkommazahlen gespeichert
werden und es dadurch bei Dezimalbrüchen
zu Rundungsfehlern kommen kann.
Besonders für Geldbeträge verbietet sich
die Benutzung von Gleitkommazahlen!
CHARACTER(n), VARCHAR(n)Zeichenketten (variabler Länge)
mit Längenangaben
Bei CHAR wird bei Bedarf bis zur
Maximallänge mit Leerzeichen aufgefüllt,
bei VARCHAR nicht
DATE, TIME, DATETIME, TIMESTAMPDatum, Zeit, Datum und Zeit, Zeitstempel
CLOB, BLOBGroße Texte, große (binäre) Daten;
können vom DBMS nur gespeichert und
gelesen, aber nicht weiter verarbeitet werden
BOOLEANwahr/falsch

Es gibt die Möglichkeit, festzulegen, ob in eine Spalte ein Wert eingetragen werden muss oder ob man die Angabe auch bewusst frei bzw undefiniert lassen kann. Ein solcher unbekannter Wert wird in SQL als NULL bezeichnet. NULL darf nicht mit der Zahl 0 verwechselt werden! Wenn NULL verboten werden soll, muss beim Anlegen der Spalte NOT NULL geschrieben werden. Primärschlüssel dürfen niemals NULL sein, deswegen kann man dort das NOT NULL auch weglassen, weil das DBMS das in diesem Fall automatisch macht. Es empfiehlt sich, alle Spalten standardmäßig mit NOT NULL anzulegen, wenn es nicht wirklich einen guten Grund gibt, warum man NULL zulassen soll. Dies erspart böse Überraschungen später, weil es den Fall ausschließt, dass ein Wert erwartet wird, aber dann doch keiner drin steht. Das Thema NULL in Verbindung mit Fremdschlüsseln wird im nächsten Teil noch eine Rolle spielen.

Im weiteren Verlauf sind die SQL-Schlüsselwörter in Großbuchstaben, selbst vergebene Namen in Kleinbuchstaben geschrieben. Zunächst sind die Befehle allgemein angegeben, anschließend folgt ein Beispiel mit konkreten Werten, das sich an den Tabellen von Teil 2 orientiert.

Die Grundstruktur von CREATE TABLE ist wie folgt:

CREATE TABLE tabelle (
 spalte DATENTYP,
 spalte DATENTYP NOT NULL,
 ...
 );

Eine Spalte wird mit dem Schlüsselwort PRIMARY KEY zum Primärschlüssel erklärt. PRIMARY KEY kann auch am Ende der CREATE TABLE-Anweisung stehen. Das ist dann sogar notwendig, wenn mehrere Spalten zu einem zusammengesetzten Primärschlüssel werden sollen.

Das Schlüsselwort AUTO_INCREMENT dient bei MySQL dazu, einen künstlich generierten Schlüssel zu erzeugen. Im Standard-SQL lautet der Befehl aber GENERATED BY DEFAULT AS IDENTITY oder GENERATED ALWAYS AS IDENTITY, je nachdem, ob man zulassen will, dass der Benutzer optional auch eigene Werte eingeben darf oder ob der Wert immer generiert werden muss. Bei MySQL verhält sich AUTO_INCREMENT wie BY DEFAULT, es darf also auch ein eigener Wert eingefügt werden. AUTO_INCREMENT funktioniert nur, wenn die Spalte vom Typ Ganzzahl und ein Schlüssel ist.

CREATE TABLE tabelle1 (
 primaerschluesselspalte INTEGER PRIMARY KEY AUTO_INCREMENT,
 spalte DATENTYP NOT NULL,
 ...
);

CREATE TABLE tabelle2 (
 spalte1 DATENTYP,
 spalte2 DATENTYP,
 spalte3 DATENTYP NOT NULL,
 PRIMARY KEY(spalte1, spalte2)
);

Ein Fremdschlüssel wird mit dem Befehl FOREIGN KEY erzeugt. Wie beim PRIMARY KEY auch gibt es in SQL die Variante, FOREIGN KEY direkt bei der Spalte oder separat normalerweise am Ende der CREATE-Anweisung zu schreiben. Bei MySQL funktioniert aber nur zweite Variante. Die andere bringt keine Fehlermeldung, wird aber stillschweigend ignoriert.

Damit der Fremdschlüssel erfolgreich angelegt werden kann, muss die Tabelle, auf die sich der Fremdschlüssel bezieht, vorher angelegt worden sein und die Fremdschlüsselspalte muss den gleichen Datentyp haben wie die Spalte, auf die er sich bezieht. (Dies ist meistens der Primärschlüssel der anderen Tabelle.)

CREATE TABLE tabelle (
 spalte1 DATENTYP,
 FOREIGN KEY(spalte1) REFERENCES andere_tabelle(spalte)
);

CREATE TABLE – Beispiel

Für die Tabellen Person, Bestellformular, Produkt und enthaelt lauten die CREATE-Statements wie folgt:

CREATE TABLE Person(
  PNr INTEGER PRIMARY KEY AUTO_INCREMENT,
  Name VARCHAR(100) NOT NULL,
  Vorname VARCHAR(100) NOT NULL
);

CREATE TABLE Bestellformular(
  AuftrNr INTEGER PRIMARY KEY AUTO_INCREMENT,
  PNr INTEGER NOT NULL,
  Zeit DATETIME NOT NULL
);

CREATE TABLE Produkt(
  ArtNr INTEGER PRIMARY KEY AUTO_INCREMENT,
  Bezeichnung VARCHAR(100) NOT NULL,
  Farbe VARCHAR(100),
  Preis DECIMAL(8,2)
);

CREATE TABLE enthaelt(
  AuftrNr INTEGER,
  ArtNr INTEGER,
  Menge INTEGER NOT NULL,
  PRIMARY KEY(AuftrNr, ArtNr),
  FOREIGN KEY(AuftrNr) REFERENCES Bestellformular(AuftrNr),
  FOREIGN KEY(ArtNr) REFERENCES Produkt(ArtNr)
);
  

Man beachte im Beispiel speziell folgende Punkte:

  • Fast alle Spalten sind NOT NULL. Bei den Primärschlüsseln kann man NOT NULL weglassen, sie sind automatisch NOT NULL. Nur bei der Spalte Farbe in der Tabelle Produkt wurde NOT NULL bewusst weggelassen, weil es Produkte geben kann, bei denen die Angabe einer Farbe nicht sinnvoll wäre.
  • Namen und Bezeichnungen sind als Zeichenketten variabler Länge angelegt. CHAR verwendet man im allgemeinen nur, wenn die Bezeichnungen wirklich alle gleich lang sind.
  • Der Preis ist DECIMAL, damit es keine Rundungsfehler gibt. Man darf auf keinen Fall binäre Gleitkommazahlen für Geldbeträge verwenden!
  • Weil es in der Praxis immer mal wieder übersehen wird: Der Preis hat 8 Stellen insgesamt, davon 6 Stellen vor und 2 nach dem Komma.
  • Die Reihenfolge, in der die Tabellen angelegt werden, ist in der Praxis wichtig, weil sonst das Anlegen der Fremdschlüssel nicht klappt.
  • Die SQL-Befehle sind hier im Beispiel nur der Deutlichkeit halber groß geschrieben. In der Praxis kann man sie auch klein schreiben.
  • Die Klammern sind wichtig!

Kurz testen!

Es folgen ganz kurz noch was zum Einfügen, Abfragen und Löschen ein paar Beispiele. Eine ausführliche Erklärung würden den Rahmen dieses Beitrags sprengen und wird später noch folgen. Nur sollte man natürlich die angelegten Tabellen ruhig mal ausprobieren!

Zum Einfügen von Daten:

INSERT INTO Produkt VALUES(100, 'Gummientchen', 'gelb', 5.50);

Oder falls Spalten generiert oder freigelassen werden sollen:

INSERT INTO Produkt(Bezeichnung, Preis) VALUES('Computerspiel Qix', 119.97);

Dabei ist folgendes zu beachten:

  • Wenn, wie im ersten Beispiel, die Angabe der Spalten, in die eingefügt werden soll, weggelassen wird, müssen alle Spalten gefüllt werden und zwar in der Reihenfolge, in der sie beim Anlegen der Tabelle angegeben wurden.
  • Zeichenketten müssen in Anführungszeichen oder Hochkommas gesetzt werden.
  • Bei Zahlen wird statt dem Komma der Punkt verwendet.

Zum Anzeigen von Daten:

SELECT * FROM Produkt;

SELECT ist ein sehr mächtiger SQL-Befehl, mit dem noch der ein oder andere Beitrag gefüllt werden wird…

Zum Löschen (des Produkts mit der Artikelnummer 100):

DELETE FROM Produkt WHERE ArtNr = 100;

Und nun viel Spaß beim Ausprobieren!

Referenzen

  • Oracle (2019): MySQL 8.0 Reference Manual (zuletzt abgerufen am 12.06.2019)
  • Jonathan Gennick (2006): SQL – kurz & gut, 2. Auflagen, O’Reilly

Lehrbücher

  • Kemper, Alfons und Eickler, André (2009): Datenbanksysteme – Eine Einführung, 7. Auflage
  • Piepmeyer, Lothar (2011): Grundkurs Datenbanksysteme – Von den Konzepten bis zur Anwendungsentwicklung, Hanser

Vorlesungsfolien