5. SQL-Grundlagen
Grundlagen der SQL-Datenbanksprache
Abschnitt betitelt „Grundlagen der SQL-Datenbanksprache“Geschichte und Zweck von SQL
Abschnitt betitelt „Geschichte und Zweck von SQL“SQL (Structured Query Language) ist eine Sprache für die Arbeit mit relationalen Datenbanken.
Sie wurde aus der früheren IBM-Sprache SEQUEL (Structured English Query Language) entwickelt.
Ziel war es, eine Datenbanksprache zu schaffen, die relativ leicht zu lesen und zu schreiben ist - auch für Menschen, die keine professionellen Programmierer sind - und die keine mathematischen Symbole wie ∀ oder ∃ benötigt (deshalb werden Relationen als Tabellen dargestellt, die mathematisch gesehen Mengen entsprechen).
Im Laufe der Zeit wurde SQL zu einem internationalen Standard. Der erste Standard wurde 1986 vom ANSI (American National Standards Institute) veröffentlicht. Seitdem wurde die Sprache mehrfach erweitert. Neue Versionen fügen mehr Funktionen hinzu, aber die meisten Datenbanksysteme stützen sich weiterhin auf den Kern des älteren SQL-92-Standards und ergänzen dann einige neuere Funktionen sowie herstellerspezifische Erweiterungen.
Modernes SQL bietet auch Unterstützung für JSON (JavaScript Object Notation). JSON ist ein kompaktes, textbasiertes Datenformat, das zum Austausch von Daten zwischen Anwendungen verwendet wird, insbesondere in der Web- und Mobilentwicklung. Es ist leicht zu lesen, unabhängig von einer bestimmten Programmiersprache und wird von vielen Werkzeugen und Bibliotheken unterstützt. Neuere Standards führen zudem fortgeschrittene Funktionen ein, etwa Mustererkennung auf Tabellenzeilen sowie Unterstützung für mehrdimensionale Daten und Graph-Abfragen, doch diese sind eher für Spezialfälle relevant und noch nicht in allen Datenbanksystemen vollständig verfügbar.
SQL ist eine interaktive Sprache. Sie erlaubt Ad-hoc-Abfragen, das heißt, Befehle können eingegeben und sofort ausgeführt werden. Gleichzeitig wird SQL innerhalb von Anwendungen eingesetzt, um mit einer Datenbank zu kommunizieren - sowohl zum Lesen als auch zum Schreiben von Daten. Mehrere SQL-Befehle können in Skripten gespeichert werden, um automatisch ausgeführt zu werden.
Die Sprache wird üblicherweise in vier Hauptgruppen von Befehlen unterteilt:
-
DDL (Data Definition Language)
Befehle zum Erstellen und Ändern der Struktur von Datenbanken, Tabellen und Indizes (zum Beispiel: Tabellen erstellen).
-
DQL (Data Query Language)
Befehle zum Abfragen und Lesen von Daten aus Tabellen (zum Beispiel: Daten auswählen).
-
DML (Data Manipulation Language)
Befehle zum Einfügen, Ändern und Löschen von Datensätzen.
-
DCL (Data Control Language)
Befehle zum Anlegen von Benutzern und zum Vergeben von Zugriffsrechten.
Zusammengefasst ist SQL eine standardisierte, weit verbreitete Sprache, die klare und strukturierte Befehle bereitstellt, um Datenstrukturen zu definieren, Daten abzurufen, Daten zu verändern und den Zugriff auf Daten in relationalen Datenbanksystemen zu steuern.
SQL-Dialekte
Abschnitt betitelt „SQL-Dialekte“In der Praxis gibt es nicht nur ein einziges “SQL”, sondern mehrere SQL-Dialekte, je nach Datenbanksystem. Alle folgen dem allgemeinen SQL-Standard, aber jedes System ergänzt eigene Funktionen, Datentypen und kleine Unterschiede in der Syntax. Das bedeutet, dass grundlegende Abfragen oft sehr ähnlich aussehen, fortgeschrittene Funktionen sich aber unterschiedlich verhalten können.
Wegen dieser Unterschiede ist SQL-Code nicht immer zu 100 % portierbar von einem Datenbanksystem zum anderen. Einfache Abfragen (zum Beispiel grundlegende SELECT-Anweisungen) funktionieren meist ohne Änderung in vielen Systemen, während komplexe Abfragen, gespeicherte Prozeduren oder spezielle Datentypen oft für jeden SQL-Dialekt angepasst werden müssen.
Grundlegender Arbeitsablauf beim Arbeiten mit Datenbanken
Abschnitt betitelt „Grundlegender Arbeitsablauf beim Arbeiten mit Datenbanken“Beim Erstellen einer Datenbank werden drei grundlegende Schritte befolgt:
-
Die Datenbank erstellen. Die Datenbank dient als Behälter, der alle Tabellen und anderen Datenbankobjekte enthält.
-
Die benötigten Tabellen erstellen. In dieser Phase wird nur die Struktur festgelegt: welche Spalten eine Tabelle hat, welche Datentypen in diesen Spalten gespeichert werden und welche Spalte (oder welche Spalten) den Primärschlüssel bildet.
-
Die Tabellen mit Daten befüllen. Tabellen sind die einzigen Datenbankobjekte, in denen Daten physisch gespeichert werden. Sobald die Daten eingefügt sind, können sie ausgewertet, geändert oder gelöscht werden.
Eine Datenbank kann mehrere Tabellen enthalten, und es können beliebig viele Datenbanken angelegt werden, um Daten nach Thema oder Projekt zu trennen. Wenn verschiedene Benutzer mit demselben Datenbanksystem arbeiten, ist es wichtig, dass passende Zugriffsrechte vergeben werden, sodass jeder Benutzer nur die Berechtigungen hat, die für ihn vorgesehen sind.
Datenbankverwaltung
Abschnitt betitelt „Datenbankverwaltung“Ein Datenbankmanagementsystem (DBMS) kann mehrere Datenbanken beherbergen. Bevor man mit einer Datenbank arbeiten kann, muss sie zunächst erstellt werden. Wenn eine Datenbank erstellt wird, dient sie als Behälter für alle Tabellen und anderen Datenbankobjekte, die später definiert werden.
Wird eine Datenbank schließlich nicht mehr benötigt, kann sie mit dem Befehl DROP DATABASE gelöscht werden. Dieser Befehl entfernt die Datenbank und ihren gesamten Inhalt dauerhaft, daher sollte er mit Vorsicht verwendet werden.
Datenbank erstellen
Abschnitt betitelt „Datenbank erstellen“Der allererste SQL-Befehl, dem man begegnet, ist der Befehl CREATE DATABASE. Dieser Befehl erstellt eine neue Datenbank im Datenbankmanagementsystem. Die Syntax kann sich zwischen verschiedenen SQL-Dialekten leicht unterscheiden, aber die grundlegende Struktur ist ähnlich.
Die Syntax zum Erstellen einer Datenbank in PostgreSQL lautet wie folgt:
CREATE DATABASE someDatabaseName[WITH OWNER userNameTEMPLATE templateENCODING encodingSpecificationTABLESPACE tablespaceName];Wobei:
someDatabaseName: Der Name der zu erstellenden Datenbank.userName: Der Name des Datenbankeigentümers.template: Die Vorlagendatenbank, aus der die neue Datenbank erstellt wird (Standard isttemplate1).encodingSpecification: Die Zeichenkodierung für die Datenbank (zum BeispielUTF8).tablespaceName: Der Tablespace, in dem die Datenbankdateien gespeichert werden.
Die Syntax zum Erstellen einer Datenbank in MariaDB oder MySQL lautet wie folgt:
CREATE DATABASE [IF NOT EXISTS] someDatabaseName;Wobei:
someDatabaseName: Der Name der zu erstellenden Datenbank.
Erstellte Datenbanken auflisten
Abschnitt betitelt „Erstellte Datenbanken auflisten“Manchmal weiß man nicht, welche Datenbanken bereits im Datenbankmanagementsystem existieren. Man braucht ein Mittel, um alle vorhandenen Datenbanken aufzulisten.
Es gibt in PostgreSQL keinen direkten SQL-Befehl, um Datenbanken aufzulisten. Stattdessen kann man den folgenden Befehl in der Kommandozeile psql verwenden:
\lEin einfacher Backslash \ gefolgt vom Buchstaben “l” listet alle Datenbanken zusammen mit ihren Eigentümern, Kodierungen und Zugriffsrechten auf.
In MariaDB oder MySQL kann man den folgenden SQL-Befehl verwenden, um alle Datenbanken aufzulisten:
SHOW DATABASES;Mit einer bestimmten Datenbank arbeiten
Abschnitt betitelt „Mit einer bestimmten Datenbank arbeiten“Bevor man Tabellen erstellen und Daten einfügen kann, muss man die Datenbank auswählen, mit der man arbeiten möchte. In MariaDB/MySQL geschieht dies mit dem Befehl USE. In PostgreSQL verbindet man sich beim Start der Kommandozeile psql mit der gewünschten Datenbank.
Das ist notwendig, weil ein Datenbankmanagementsystem mehrere Datenbanken enthalten kann und man jeweils angeben muss, mit welcher man arbeiten möchte.
In PostgreSQL verbindet man sich beim Start der Kommandozeile psql mit einer bestimmten Datenbank. Man kann dies tun, indem man den Datenbanknamen als Argument angibt:
\c databaseNameWobei:
databaseName: Der Name der Datenbank, mit der man sich verbinden möchte.
In MariaDB oder MySQL kann man den Befehl USE verwenden, um eine bestimmte Datenbank auszuwählen:
USE databaseName;Wobei:
databaseName: Der Name der Datenbank, mit der man arbeiten möchte.
Eine Datenbank löschen
Abschnitt betitelt „Eine Datenbank löschen“Wird eine Datenbank schließlich nicht mehr benötigt, kann sie mit dem Befehl DROP DATABASE gelöscht werden. Dieser Befehl entfernt die Datenbank und ihren gesamten Inhalt dauerhaft, daher sollte er mit Vorsicht verwendet werden.
Um eine Datenbank in PostgreSQL zu löschen, kann man den folgenden Befehl verwenden:
DROP DATABASE databaseName;Wobei:
databaseName: Der Name der zu löschenden Datenbank.
In MariaDB oder MySQL kann man den Befehl DROP DATABASE verwenden, um eine bestimmte Datenbank zu löschen:
DROP DATABASE [IF EXISTS] databaseName;Wobei:
databaseName: Der Name der zu löschenden Datenbank.
Tabellenverwaltung
Abschnitt betitelt „Tabellenverwaltung“Tabellen (Relationen) sind die wichtigsten Objekte (“first class citizens”) in einer Datenbank. In diesen Tabellen werden die Daten gespeichert. Jeder Zugriff auf die Daten erfolgt über die Tabellen. Für jede Abfrage oder Auswertung muss der Name der Tabelle angegeben werden. Die Datenbank dient als Behälter für die logisch zusammengehörigen Tabellen. Der Tabellenname muss innerhalb einer Datenbank eindeutig sein, derselbe Name darf jedoch in mehreren Datenbanken eines DBMS verwendet werden.
Eine Tabelle besteht aus einzelnen Feldern (Datenfeldern, Attributen, Spalten). Die Struktur bzw. das Schema der Tabelle wird durch die Namen und Datentypen dieser Felder definiert. Zusammengehörige Daten werden in eine Zeile der Tabelle eingetragen. Sie bilden einen Datensatz oder ein Tupel.
Um eine Tabelle erstellen zu können, wird das Ausführungsrecht für die Anweisung CREATE TABLE benötigt. Der Administrator vergibt dieses Recht. Der Benutzer, der die Tabelle erstellt, wird dann ihr Eigentümer.
Eine Tabelle erstellen
Abschnitt betitelt „Eine Tabelle erstellen“Um eine Tabelle zu erstellen, wird der Befehl CREATE TABLE verwendet. Die Syntax kann sich zwischen verschiedenen SQL-Dialekten leicht unterscheiden, aber die grundlegende Struktur ist ähnlich. Die Datenbank muss nicht erneut angegeben werden, da die Tabelle in der aktuell ausgewählten Datenbank erstellt wird.
Die Syntax zum Erstellen einer Tabelle ist in PostgreSQL und MariaDB/MySQL sehr ähnlich. Es gibt jedoch Unterschiede bei den unterstützten Datentypen und Constraints.
Um eine Tabelle in PostgreSQL zu erstellen, kann man den folgenden Befehl verwenden:
CREATE TABLE tableName ( column1 dataType1 [constraints], column2 dataType2 [constraints], ... columnN dataTypeN [constraints]);Wobei:
tableName: Der Name der zu erstellenden Tabelle.columnX: Der Name einer Spalte in der Tabelle.dataTypeX: Der Datentyp der Spalte (zum BeispielINTEGER,VARCHAR(255),DATE).constraints: Optionale Constraints für die Spalte (zum BeispielPRIMARY KEY,NOT NULL).
In MariaDB oder MySQL kann man eine Tabelle mit dem folgenden Befehl erstellen:
CREATE TABLE tableName ( column1 dataType1 [constraints], column2 dataType2 [constraints], ... columnN dataTypeN [constraints]);Wobei:
tableName: Der Name der zu erstellenden Tabelle.columnX: Der Name einer Spalte in der Tabelle.dataTypeX: Der Datentyp der Spalte (zum BeispielINTEGER,VARCHAR(255),DATE).constraints: Optionale Constraints für die Spalte (zum BeispielPRIMARY KEY,NOT NULL).
Aus einem ER-Modell abgeleitet, wird die Tabellenstruktur mit dem Befehl CREATE TABLE erstellt. Jede Entität im ER-Modell entspricht einer Tabelle in der Datenbank. Die Attribute der Entität werden zu den Spalten der Tabelle, und die Beziehungen zwischen Entitäten werden über Fremdschlüssel dargestellt.
Datentypen
Abschnitt betitelt „Datentypen“Beim Definieren einer Tabelle ist es wichtig, für jede Spalte den Datentyp anzugeben. Der Datentyp legt fest, welche Art von Daten in dieser Spalte gespeichert werden kann (zum Beispiel Ganzzahlen, Text, Datumswerte usw.) und wie viel Platz dafür reserviert wird.
Datentypen können sich zwischen verschiedenen Datenbanksystemen unterscheiden, aber es gibt einige gängige, die weit verbreitet sind. Sie lassen sich grob in mehrere Gruppen einteilen.
Numerische Datentypen für Ganzzahlen:
| Datentyp | Größe | Beschreibung | Beispielwerte |
|---|---|---|---|
INT oder INTEGER | 4 Bytes | Standard-Ganzzahltyp | 42, -7, 0 |
SMALLINT | 2 Bytes | Ganzzahltyp mit kleinerem Bereich | 32000, -32000 |
BIGINT | 8 Bytes | Ganzzahltyp mit größerem Bereich | 9223372036854775807 |
Numerische Datentypen für Gleitkommawerte:
| Datentyp | Größe | Beschreibung | Beispielwerte |
|---|---|---|---|
FLOAT oder REAL | 4 Bytes | Standard-Gleitkommatyp | 42.0, -7.5, 0.0 |
DOUBLE oder DOUBLE PRECISION | 8 Bytes | Gleitkommatyp mit doppelter Genauigkeit | 32000.123, -32000.456 |
DECIMAL (p,s) oder NUMERIC (p,s) | Variabel | Exakter numerischer Typ mit fester Genauigkeit | 12345.67, -12345.67 |
Datums- und Zeit-Datentypen:
| Datentyp | Größe | Beschreibung | Beispielwerte |
|---|---|---|---|
DATE | 4 Bytes | Ein einzelnes Datum | 01.01.2026 |
TIME | 8 Bytes | Zeitwert | 12:34:56 |
TIMESTAMP | 8 Bytes | Ein Wert, der Datum und Zeit kombiniert | 01.01.2026 12:34:56 |
Zeitwerte werden üblicherweise im 24-Stunden-Format gespeichert: HH:MM:SS (Stunden:Minuten:Sekunden). Datumswerte werden je nach Datenbanksystem und Locale-Einstellungen oft im Format YYYY-MM-DD (Jahr-Monat-Tag) oder DD-MM-YYYY gespeichert.
Text-Datentypen:
| Datentyp | Größe | Beschreibung | Beispielwerte |
|---|---|---|---|
CHAR(n) | n Bytes | Zeichenkette mit fester Länge | ’Hello’ |
VARCHAR(n) | Bis zu n Bytes | Zeichenkette mit variabler Länge | ’Hello, World!’ |
TEXT | Variabel | Große Textdaten | ’This is a long text…’ |
Binäre Datentypen:
| Datentyp | Größe | Beschreibung | Beispielwerte |
|---|---|---|---|
BINARY(n) | n Bytes | Binärdaten mit fester Länge | 0x4D5A |
VARBINARY(n) | Bis zu n Bytes | Binärdaten mit variabler Länge | 0x4D5A3B |
BYTEA | Variabel | Große Binärdaten (PostgreSQL) | (Bilder, Dateien usw.) |
BLOB | Variabel | Große Binärdaten (MariaDB / MySQL) | (Bilder, Dateien usw.) |
Boolescher Datentyp:
| Datentyp | Größe | Beschreibung | Beispielwerte |
|---|---|---|---|
BOOLEAN | 1 Byte | Stellt wahr/falsch dar | TRUE, FALSE |
Ein Hinweis zu DECIMAL vs. FLOAT
Abschnitt betitelt „Ein Hinweis zu DECIMAL vs. FLOAT“In SQL sind DECIMAL und NUMERIC Festkomma-Zahlentypen, die verwendet werden, wenn exakte Werte benötigt werden - insbesondere für Geld, Mengen oder Messwerte, bei denen Rundungsfehler nicht akzeptabel sind.
Im Grunde speichern sowohl DECIMAL als auch NUMERIC Zahlen mit:
- einer festen Gesamtanzahl von Ziffern (Precision/Genauigkeit)
- einer festen Anzahl von Ziffern nach dem Komma (Scale/Nachkommastellen)
Allgemeine Syntax:
DECIMAL(precision, scale)NUMERIC(precision, scale)precision= Gesamtanzahl der Ziffern (vor + nach dem Komma)scale= Anzahl der Ziffern nach dem Komma
Wird scale weggelassen, setzen viele Systeme standardmäßig 0 (ganzzahlartig) oder gelegentlich den Standardwert der Implementierung (oft 0 oder gleich der Precision). Das hängt vom DBMS ab. Im SQL-Standard sind DECIMAL und NUMERIC als gleichwertig gedacht. In der Praxis behandeln die meisten Datenbanksysteme sie als Synonyme.
Beispiel:
DECIMAL(7, 2)precision = 7→ Gesamtziffern = 7scale = 2→ 2 Ziffern nach dem Komma
Das erlaubt also Zahlen von:
- -99999.99 bis +99999.99
weil:
- 5 Ziffern vor dem Komma
- 2 Ziffern nach dem Komma
- → insgesamt = 7 Ziffern
Gültige Werte für DECIMAL(7, 2):
0.0012.3499999.99-123.45
Ungültig (zu viele Ziffern oder zu viele Nachkommastellen):
123456.78→ 6 Ziffern vor dem Komma (benötigt Precision ≥ 8)1.234→ 3 Ziffern nach dem Komma (Scale = 2, würde also gerundet oder abgewiesen)
NUMERIC(p,s) muss exakt die angegebene Precision haben. DECIMAL(p, s) darf intern etwas mehr Precision verwenden, verhält sich aus Sicht des Benutzers aber logisch gleich.
Gleitkommatypen (FLOAT, REAL, DOUBLE PRECISION usw.) sind näherungsweise:
- Sie werden im Binärformat gespeichert und können nicht alle Dezimalbrüche exakt darstellen.
- Das führt zu Rundungsartefakten wie
0.1 + 0.2, das zu0.30000000000000004wird.
DECIMAL/NUMERIC sind exakte Dezimaltypen:
- Berechnungen mit Geld (Preise, Steuern, Salden) dürfen nicht durch binäre Rundungsfehler beeinflusst werden.
- Verwenden Sie für Währung, präzise Finanzberechnungen sowie Zählungen/Mengen mit festen Nachkommastellen immer
DECIMAL/NUMERIC.
Beispielproblem mit Float:
-- Speichert möglicherweise nicht exakt 0.10price FLOAT = 0.10
-- Kann wegen binärer Rundung seltsame Ergebnisse liefernBesser:
price DECIMAL(10, 2) = 0.10 -- Genau zwei NachkommastellenHäufig verwendet für Geld und Finanzdaten, also Geldbeträge wie Preise, Gehälter, Steuern usw.
Wie viele Bytes zum Speichern von DECIMAL-Werten benötigt werden, hängt vom DBMS und der angegebenen Precision/Scale ab. Generell benötigt höhere Precision mehr Speicherplatz.
Beispiel für den Speicherbedarf von DECIMAL/NUMERIC in Transact-SQL (SQL Server) decimal and numeric (Transact-SQL):
| Precision | Speicher in Bytes |
|---|---|
| 1 - 9 | 5 |
| 10-19 | 9 |
| 20-28 | 13 |
| 29-38 | 17 |
Modifizierer
Abschnitt betitelt „Modifizierer“Zusätzlich zu den grundlegenden Datentypen stellt SQL auch Modifizierer bereit, mit denen sich die Eigenschaften einer Spalte weiter spezifizieren lassen. Gängige Modifizierer sind:
UNSIGNED: Legt fest, dass eine numerische Spalte nur nicht-negative Werte speichern darf (also Null und positive Zahlen). Dies wird oft für Felder wie IDs oder Zählungen verwendet, bei denen negative Werte keinen Sinn ergeben.ZEROFILL: (MariaDB / MySQL-spezifisch) Füllt numerische Werte bei der Anzeige mit führenden Nullen auf. Dies wird oft für Felder wie Kontonummern oder Codes verwendet, bei denen eine feste Länge gewünscht ist.- MariaDB / MySQL:
AUTO_INCREMENTerzeugt automatisch einen eindeutigen Wert für jede neu in die Tabelle eingefügte Zeile. Dies wird oft für Primärschlüsselspalten verwendet. - PostgreSQL:
SERIALerzeugt automatisch einen eindeutigen Wert für jede neu in die Tabelle eingefügte Zeile. Dies wird oft für Primärschlüsselspalten verwendet. DEFAULT: Legt einen Standardwert für eine Spalte fest, falls bei einer Einfügeoperation kein Wert angegeben wird.
Constraints
Abschnitt betitelt „Constraints“Beim Definieren einer Tabelle können Sie auch Constraints (Bedingungen) für die Spalten angeben. Constraints sind Regeln, die die Art der Daten einschränken, die in einer Spalte gespeichert werden können. Gängige Constraints sind:
PRIMARY KEY: Identifiziert jeden Datensatz in der Tabelle eindeutig: markiert eine Spalte (oder eine Kombination von Spalten) als den Primärschlüssel der Tabelle.FOREIGN KEY,REFERENCES: Stellt die referenzielle Integrität zwischen zwei Tabellen sicher: markiert eine Spalte (oder eine Kombination von Spalten) als Fremdschlüssel, der auf den Primärschlüssel einer anderen Tabelle verweist.NOT NULL: Stellt sicher, dass eine Spalte keinen NULL-Wert haben kann. Jede Zeile muss einen Wert für diese Spalte haben.UNIQUE: Stellt sicher, dass alle Werte in einer Spalte eindeutig sind, also keine doppelten Werte erlaubt sind. Typischerweise für Felder wie E-Mail-Adressen oder Benutzernamen verwendet.CHECK: Stellt sicher, dass alle Werte in einer Spalte eine bestimmte Bedingung erfüllen.
Sie können Constraints entweder auf Spaltenebene (direkt nach dem Datentyp) oder auf Tabellenebene (nachdem alle Spalten definiert wurden) definieren.
Constraints auf Zeilenebene:
CREATE TABLE blog_post ( post_id SERIAL PRIMARY KEY, author_id INTEGER NOT NULL REFERENCES app_user(user_id) ON DELETE RESTRICT ON UPDATE CASCADE, slug VARCHAR(120) NOT NULL UNIQUE, title TEXT NOT NULL, body TEXT NOT NULL, status VARCHAR(20) NOT NULL CHECK (status IN ('DRAFT', 'PUBLISHED')), published_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW());Constraints auf Tabellenebene:
CREATE TABLE blog_post ( post_id SERIAL, author_id INTEGER NOT NULL, slug VARCHAR(120) NOT NULL, title TEXT NOT NULL, body TEXT NOT NULL, status VARCHAR(20) NOT NULL, published_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT pk_blog_post PRIMARY KEY (post_id), CONSTRAINT uq_blog_post_slug UNIQUE (slug), CONSTRAINT ck_blog_post_status CHECK (status IN ('DRAFT', 'PUBLISHED')), CONSTRAINT fk_blog_post_author FOREIGN KEY (author_id) REFERENCES app_user(user_id) ON DELETE RESTRICT ON UPDATE CASCADE);Beispiele
Abschnitt betitelt „Beispiele“Benutzertabelle (Identity + Text + Booleans + Zeitstempel)
CREATE TABLE app_user ( user_id SERIAL PRIMARY KEY, email VARCHAR(320) NOT NULL UNIQUE, display_name TEXT NOT NULL, is_active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW());Produkttabelle (Identity + Text + Numeric + Zeitstempel)
CREATE TABLE product ( product_id SERIAL PRIMARY KEY, serial_number VARCHAR(64) NOT NULL UNIQUE, name TEXT NOT NULL, price NUMERIC(12,2) NOT NULL CHECK (price >= 0), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW());Blogbeitragstabelle (Fremdschlüssel + Text + Zeitstempel)
CREATE TABLE blog_post ( post_id SERIAL PRIMARY KEY, author_id INTEGER NOT NULL REFERENCES app_user(user_id), title TEXT NOT NULL, body TEXT NOT NULL, published_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW());Benutzertabelle (Identity + Text + Booleans + Zeitstempel)
CREATE TABLE app_user ( user_id INT AUTO_INCREMENT PRIMARY KEY, email VARCHAR(320) NOT NULL UNIQUE, display_name TEXT NOT NULL, is_active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP);Produkttabelle (Identity + Text + Numeric + Zeitstempel)
CREATE TABLE product ( product_id INT AUTO_INCREMENT PRIMARY KEY, serial_number VARCHAR(64) NOT NULL UNIQUE, name TEXT NOT NULL, price DECIMAL(12,2) NOT NULL CHECK (price >= 0), created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP);Blogbeitragstabelle (Fremdschlüssel + Text + Zeitstempel)
CREATE TABLE blog_post ( post_id INT AUTO_INCREMENT PRIMARY KEY, author_id INT NOT NULL REFERENCES app_user(user_id), title TEXT NOT NULL, body TEXT NOT NULL, published_at TIMESTAMP NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP)Ein “Tabellen-Budget” ist eine pragmatische Kapazitätsabschätzung: Zeilenbreite (Bytes pro Zeile) × erwartete Zeilenanzahl ergibt eine Näherung dafür, wie viel Speicher eine Tabelle verbrauchen wird. Das ist früh im Schemaentwurf nützlich, weil es zwingt, in Einheiten zu denken: “Wenn jede Zeile etwa 350 Bytes groß ist und wir 50 Millionen Zeilen erwarten, dann liegt allein diese Tabelle in der Größenordnung von 17,5 GB vor Overhead.” Selbst wenn die Schätzung grob ist, hilft sie, Entwurfsentscheidungen zu erkennen, die schlecht skalieren.
Das hilft, mögliche Probleme früh zu erkennen, etwa die Wahl von Datentypen, die für das erwartete Datenvolumen zu groß sind. Zum Beispiel verschwendet die Verwendung von BIGINT für eine Spalte, die nur kleine Ganzzahlen speichern wird, Platz. Stattdessen wäre SMALLINT oder INT effizienter.
Hier ist ein einfacher Ansatz zur Abschätzung eines Tabellen-Budgets:
-
Zeilenbreite schätzen: Summieren Sie die Größen aller Spalten in Bytes. Berücksichtigen Sie Datentypen und etwaigen Overhead (z. B. haben Typen variabler Länge wie
VARCHARzusätzliche Bytes für die Länge).Typen fester Breite sind unkompliziert (typische Heap-Größen):
- BOOLEAN = 1 Byte (plus Ausrichtungseffekte)
- SMALLINT = 2 Bytes
- INTEGER = 4 Bytes
- BIGINT = 8 Bytes
- TIMESTAMP / TIMESTAMPTZ = 8 Bytes
- UUID = 16 Bytes
Typen variabler Breite (TEXT, VARCHAR, BYTEA, JSONB, NUMERIC usw.) sind:
- durchschnittliche Nutzdaten-Bytes (z. B. Zeichenkettenlänge in Bytes unter UTF-8), plus
- ein Längen-Header variabler Größe (üblicherweise 4 Bytes, manchmal 1 Byte für sehr kurze Werte), plus
- möglicher Overhead für Ausrichtung/Padding.
Beispiel:
email VARCHAR(320)mit einer durchschnittlichen E-Mail-Länge von 50 Bytes: 50 Bytes + 4 Bytes (Header) = 54 Bytes (tatsächlich mehr wegen Padding/Ausrichtung, aber die Länge kann auch in nur 1 einzigen Byte kodiert sein). Das sind jedoch Schätzungen; der tatsächliche Speicher kann aufgrund von Implementierungsdetails variieren. -
Zeilenanzahl schätzen: Schätzen Sie basierend auf der erwarteten Nutzung, wie viele Zeilen die Tabelle aufnehmen wird.
-
Tabellengröße berechnen: Multiplizieren Sie die Zeilenbreite mit der Zeilenanzahl, um eine geschätzte Tabellengröße zu erhalten.
Tabellenstruktur ändern
Abschnitt betitelt „Tabellenstruktur ändern“Das Ändern der Struktur einer bestehenden Tabelle erfolgt mit dem Befehl ALTER TABLE. Dieser Befehl erlaubt es, Spalten hinzuzufügen, zu ändern oder zu löschen sowie Constraints und andere Eigenschaften der Tabelle zu ändern.
Die Änderung einer Tabelle kann auf verschiedene Weise erfolgen, je nach der gewünschten Änderung. Gängige Operationen sind:
- Eine neue Spalte hinzufügen.
- Eine bestehende Spalte ändern (z. B. ihren Datentyp oder ihre Constraints ändern).
- Eine Spalte löschen.
Im Hinblick auf Constraints können Sie außerdem
- Ein neues Constraint hinzufügen (z. B. einen Primär- oder Fremdschlüssel hinzufügen).
- Ein bestehendes Constraint ändern (z. B. das Verhalten eines Fremdschlüssels beim Löschen ändern).
- Ein Constraint löschen.
- Eine Spalte hinzufügen
ALTER TABLE employeesADD COLUMN phone varchar(30);- Eine Spalte umbenennen
ALTER TABLE employeesRENAME COLUMN phone TO phone_number;- Eine Spalte löschen
ALTER TABLE employeesDROP COLUMN phone_number;- Ein Constraint hinzufügen (Beispiele)
ALTER TABLE employeesADD CONSTRAINT employees_salary_nonnegativeCHECK (salary >= 0);ALTER TABLE employeesADD CONSTRAINT employees_email_uniqueUNIQUE (email);- Ein Constraint löschen
ALTER TABLE employeesDROP CONSTRAINT employees_email_unique;- Eine Spalte hinzufügen
ALTER TABLE employeesADD COLUMN phone VARCHAR(30);- Eine Spalte umbenennen
ALTER TABLE employeesRENAME COLUMN phone TO phone_number;- Eine Spalte löschen
ALTER TABLE employeesDROP COLUMN phone_number;- Ein Constraint hinzufügen
ALTER TABLE employeesADD CONSTRAINT employees_email_uniqueUNIQUE (email);ALTER TABLE employeesADD CONSTRAINT employees_department_fkFOREIGN KEY (department_id) REFERENCES departments(id);- Ein Constraint löschen
ALTER TABLE employeesDROP INDEX employees_email_unique;ALTER TABLE employeesDROP FOREIGN KEY employees_department_fk;Eine Tabelle löschen
Abschnitt betitelt „Eine Tabelle löschen“Das Löschen einer Tabelle erfolgt mit dem Befehl DROP TABLE. Dieser Befehl entfernt die Tabelle und alle ihre Daten dauerhaft aus der Datenbank.
Beispiel:
- Ein einfaches Löschen:
DROP TABLE posts;- Löschen mit Cascade (entfernt auch abhängige Objekte, z. B. Fremdschlüssel in anderen Tabellen), falls die Tabelle existiert:
DROP TABLE IF EXISTS users CASCADE;- Ein einfaches Löschen:
DROP TABLE posts;- Löschen, falls die Tabelle existiert:
DROP TABLE IF EXISTS users;Lernergebnisse: Was Sie nach diesem Kapitel können sollten
Abschnitt betitelt „Lernergebnisse: Was Sie nach diesem Kapitel können sollten“Nach Abschluss dieses Kapitels sollten Schülerinnen und Schüler in der Lage sein:
- Nennen: die vier SQL-Befehlsgruppen (DDL, DQL, DML, DCL) und gängige Datentypen nennen.
- Beschreiben: Zweck und Geschichte von SQL sowie das Konzept der SQL-Dialekte beschreiben.
- Anwenden: Datenbanken und Tabellen mit
CREATE,ALTERundDROPanlegen, ändern und löschen. - Analysieren: für eine gegebene Spalte einen passenden Datentyp und geeignete Constraints auswählen (z. B.
DECIMALvs.FLOAT). - Beurteilen: die Auswirkung von Datentyp- und Constraint-Entscheidungen auf Speicherbedarf und Datenqualität beurteilen.