Zum Inhalt springen

5. SQL-Grundlagen

Zu Zen-Modus wechseln

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.

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:

  1. Die Datenbank erstellen. Die Datenbank dient als Behälter, der alle Tabellen und anderen Datenbankobjekte enthält.

  2. 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.

  3. 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.

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.

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 userName
TEMPLATE template
ENCODING encodingSpecification
TABLESPACE 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 ist template1).
  • encodingSpecification: Die Zeichenkodierung für die Datenbank (zum Beispiel UTF8).
  • tablespaceName: Der Tablespace, in dem die Datenbankdateien gespeichert werden.

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:

\l

Ein einfacher Backslash \ gefolgt vom Buchstaben “l” listet alle Datenbanken zusammen mit ihren Eigentümern, Kodierungen und Zugriffsrechten auf.

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 databaseName

Wobei:

  • databaseName: Der Name der Datenbank, mit der man sich verbinden möchte.

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.

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.

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 Beispiel INTEGER, VARCHAR(255), DATE).
  • constraints: Optionale Constraints für die Spalte (zum Beispiel PRIMARY 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.

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:

DatentypGrößeBeschreibungBeispielwerte
INT oder INTEGER4 BytesStandard-Ganzzahltyp42, -7, 0
SMALLINT2 BytesGanzzahltyp mit kleinerem Bereich32000, -32000
BIGINT8 BytesGanzzahltyp mit größerem Bereich9223372036854775807

Numerische Datentypen für Gleitkommawerte:

DatentypGrößeBeschreibungBeispielwerte
FLOAT oder REAL4 BytesStandard-Gleitkommatyp42.0, -7.5, 0.0
DOUBLE oder DOUBLE PRECISION8 BytesGleitkommatyp mit doppelter Genauigkeit32000.123, -32000.456
DECIMAL (p,s) oder NUMERIC (p,s)VariabelExakter numerischer Typ mit fester Genauigkeit12345.67, -12345.67

Datums- und Zeit-Datentypen:

DatentypGrößeBeschreibungBeispielwerte
DATE4 BytesEin einzelnes Datum01.01.2026
TIME8 BytesZeitwert12:34:56
TIMESTAMP8 BytesEin Wert, der Datum und Zeit kombiniert01.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:

DatentypGrößeBeschreibungBeispielwerte
CHAR(n)n BytesZeichenkette mit fester Länge’Hello’
VARCHAR(n)Bis zu n BytesZeichenkette mit variabler Länge’Hello, World!’
TEXTVariabelGroße Textdaten’This is a long text…’

Binäre Datentypen:

DatentypGrößeBeschreibungBeispielwerte
BINARY(n)n BytesBinärdaten mit fester Länge0x4D5A
VARBINARY(n)Bis zu n BytesBinärdaten mit variabler Länge0x4D5A3B
BYTEAVariabelGroße Binärdaten (PostgreSQL)(Bilder, Dateien usw.)
BLOBVariabelGroße Binärdaten (MariaDB / MySQL)(Bilder, Dateien usw.)

Boolescher Datentyp:

DatentypGrößeBeschreibungBeispielwerte
BOOLEAN1 ByteStellt wahr/falsch darTRUE, FALSE

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 = 7
  • scale = 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.00
  • 12.34
  • 99999.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 zu 0.30000000000000004 wird.

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.10
price FLOAT = 0.10
-- Kann wegen binärer Rundung seltsame Ergebnisse liefern

Besser:

price DECIMAL(10, 2) = 0.10 -- Genau zwei Nachkommastellen

Hä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):

PrecisionSpeicher in Bytes
1 - 95
10-199
20-2813
29-3817

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_INCREMENT erzeugt automatisch einen eindeutigen Wert für jede neu in die Tabelle eingefügte Zeile. Dies wird oft für Primärschlüsselspalten verwendet.
  • PostgreSQL: SERIAL erzeugt 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.

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
);

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()
);

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:

  1. 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 VARCHAR zusä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.

  2. Zeilenanzahl schätzen: Schätzen Sie basierend auf der erwarteten Nutzung, wie viele Zeilen die Tabelle aufnehmen wird.

  3. Tabellengröße berechnen: Multiplizieren Sie die Zeilenbreite mit der Zeilenanzahl, um eine geschätzte Tabellengröße zu erhalten.

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.
  1. Eine Spalte hinzufügen
ALTER TABLE employees
ADD COLUMN phone varchar(30);
  1. Eine Spalte umbenennen
ALTER TABLE employees
RENAME COLUMN phone TO phone_number;
  1. Eine Spalte löschen
ALTER TABLE employees
DROP COLUMN phone_number;
  1. Ein Constraint hinzufügen (Beispiele)
ALTER TABLE employees
ADD CONSTRAINT employees_salary_nonnegative
CHECK (salary >= 0);
ALTER TABLE employees
ADD CONSTRAINT employees_email_unique
UNIQUE (email);
  1. Ein Constraint löschen
ALTER TABLE employees
DROP CONSTRAINT employees_email_unique;

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:

  1. Ein einfaches Löschen:
DROP TABLE posts;
  1. 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;

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, ALTER und DROP anlegen, ändern und löschen.
  • Analysieren: für eine gegebene Spalte einen passenden Datentyp und geeignete Constraints auswählen (z. B. DECIMAL vs. FLOAT).
  • Beurteilen: die Auswirkung von Datentyp- und Constraint-Entscheidungen auf Speicherbedarf und Datenqualität beurteilen.