Skip to content

Ausblick & Weiterführende Themen

Fast geschafft...

In den vorherigen Kapiteln hast du die Grundlagen relationaler Datenbanken mit PostgreSQL kennengelernt. Du kannst jetzt:

  • ✅ Datenbanken modellieren und entwerfen
  • ✅ Tabellen erstellen und Beziehungen definieren
  • ✅ Daten einfügen, ändern und löschen
  • ✅ Komplexe Abfragen mit Joins und Aggregationen schreiben
  • ✅ Datenintegrität mit Constraints sicherstellen
  • ✅ Transaktionen für sichere Datenoperationen nutzen

Doch die Welt der Datenbanken ist viel größer als das, was wir bisher gesehen haben. In diesem abschließenden Kapitel werfen wir einen Blick über den Tellerrand und schauen uns weiterführende Themen an, die in professionellen Umgebungen wichtig sind.


Wichtiger Hinweis

In diesem Kapitel wird ein Ausblick auf weiterführende Themen gegeben. Alle Code Snippets können wie bisher ausgeführt und getestet werden. Eine detailierte Beschreibung und Erklärung der einzelnen Themen gibt es in diesem Kapitel nicht. Trotzdem kann jeder versuchen den Code nachzuvollziehen und gegebenenfalls mittels Recherche eine Erklärung zu finden.

Datenbank-Setup

Für die folgenden Beispiele erstellen wir eine E-Commerce/Online-Shop-Datenbank. In dieser Datenbank werden Produkte, Bestellungen und Lagerbestände verwaltet.

-- Datenbank erstellen
CREATE DATABASE shop_db;

-- Zur Datenbank wechseln
\c shop_db

-- Tabelle: Produkte
CREATE TABLE produkte (
    produkt_id SERIAL PRIMARY KEY,
    produktname VARCHAR(200) NOT NULL,
    kategorie VARCHAR(100),
    preis NUMERIC(10, 2) NOT NULL CHECK (preis >= 0),
    lagerbestand INTEGER NOT NULL DEFAULT 0 CHECK (lagerbestand >= 0),
    aktiv BOOLEAN DEFAULT TRUE,
    erstellt_am TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    letzte_aenderung TIMESTAMP
);

-- Tabelle: Bestellungen
CREATE TABLE bestellungen (
    bestell_id SERIAL PRIMARY KEY,
    kunde VARCHAR(200) NOT NULL,
    bestelldatum TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    status VARCHAR(50) DEFAULT 'offen',
    gesamtbetrag NUMERIC(12, 2)
);

-- Tabelle: Bestellpositionen
CREATE TABLE bestellpositionen (
    position_id SERIAL PRIMARY KEY,
    bestell_id INTEGER REFERENCES bestellungen(bestell_id) ON DELETE CASCADE,
    produkt_id INTEGER REFERENCES produkte(produkt_id),
    menge INTEGER NOT NULL CHECK (menge > 0),
    einzelpreis NUMERIC(10, 2) NOT NULL
);

-- Testdaten: Produkte
INSERT INTO produkte (produktname, kategorie, preis, lagerbestand) VALUES
('Laptop ThinkPad X1', 'Elektronik', 1299.99, 15),
('Wireless Mouse MX3', 'Zubehör', 79.99, 50),
('USB-C Hub 7-Port', 'Zubehör', 49.99, 30),
('Monitor 27" 4K', 'Elektronik', 449.99, 8),
('Mechanische Tastatur', 'Zubehör', 129.99, 20),
('Webcam HD Pro', 'Elektronik', 89.99, 0),
('Laptop-Tasche Premium', 'Zubehör', 59.99, 25);

-- Testdaten: Bestellungen
INSERT INTO bestellungen (kunde, status, gesamtbetrag) VALUES
('Anna Schmidt', 'abgeschlossen', 1429.98),
('Thomas Weber', 'in_bearbeitung', 179.98),
('Lisa Miller', 'offen', 449.99);

-- Testdaten: Bestellpositionen
INSERT INTO bestellpositionen (bestell_id, produkt_id, menge, einzelpreis) VALUES
(1, 1, 1, 1299.99),  -- Anna: Laptop
(1, 2, 1, 79.99),     -- Anna: Mouse
(1, 3, 1, 49.99),     -- Anna: Hub
(2, 2, 1, 79.99),     -- Thomas: Mouse
(2, 5, 1, 129.99),    -- Thomas: Tastatur
(3, 4, 1, 449.99);    -- Lisa: Monitor

Views (Sichten)

Eine View ist eine virtuelle Tabelle, die auf einer oder mehreren echten Tabellen basiert. Views speichern keine eigenen Daten, sondern definieren eine gespeicherte Abfrage, die bei jedem Aufruf ausgeführt wird. Allgemein lautet der Syntax

CREATE VIEW view_name AS
SELECT spalte1, spalte2, ...
FROM tabelle
WHERE bedingung;

Betrachten wir das ganze anhand eines Beispiels.

View für verfügbare Produkte

Wir erstellen eine View, die nur verfügbare Produkte zeigt (auf Lager und aktiv):

CREATE VIEW verfuegbare_produkte AS
SELECT
    produkt_id,
    produktname,
    kategorie,
    preis,
    lagerbestand
FROM produkte
WHERE aktiv = TRUE
  AND lagerbestand > 0
ORDER BY produktname;

Anschließend können wir die View verwenden:

-- View verwenden wie eine normale Tabelle
SELECT * FROM verfuegbare_produkte;
Output
 produkt_id |      produktname      | kategorie  |  preis  | lagerbestand
------------+-----------------------+------------+---------+--------------
          7 | Laptop-Tasche Premium | Zubehör    |   59.99 |           25
          1 | Laptop ThinkPad X1    | Elektronik | 1299.99 |           15
          5 | Mechanische Tastatur  | Zubehör    |  129.99 |           20
          4 | Monitor 27" 4K        | Elektronik |  449.99 |            8
          3 | USB-C Hub 7-Port      | Zubehör    |   49.99 |           30
          2 | Wireless Mouse MX3    | Zubehör    |   79.99 |           50
(6 rows)
weitere Beispiele

Eine komplexere View kann mehrere Tabellen kombinieren:

CREATE VIEW bestelluebersicht AS
SELECT
    b.bestell_id,
    b.kunde,
    b.bestelldatum,
    b.status,
    COUNT(bp.position_id) AS anzahl_artikel,
    SUM(bp.menge * bp.einzelpreis) AS gesamtbetrag
FROM bestellungen b
LEFT JOIN bestellpositionen bp ON b.bestell_id = bp.bestell_id
GROUP BY b.bestell_id, b.kunde, b.bestelldatum, b.status
ORDER BY b.bestelldatum DESC;
SELECT * FROM bestelluebersicht;
Output
 bestell_id |    kunde     |        bestelldatum        |     status     | anzahl_artikel | gesamtbetrag
------------+--------------+----------------------------+----------------+----------------+--------------
          3 | Lisa Miller  | 2025-11-26 09:45:08.313595 | offen          |              1 |       449.99
          2 | Thomas Weber | 2025-11-26 09:45:08.313595 | in_bearbeitung |              2 |       209.98
          1 | Anna Schmidt | 2025-11-26 09:45:08.313595 | abgeschlossen  |              3 |      1429.97
(3 rows)

Views haben wir nahezu alles im Leben Vor- und Nachteile. Diese wind nachfolgend aufgelistet.

Vorteile Nachteile
✅ Vereinfachung komplexer Joins ❌ Performance-Einbußen bei komplexen Views
✅ Sicherheit durch Datenbeschränkung ❌ Eingeschränkte Datenänderung (UPDATE/INSERT)
✅ Konsistente Abfragelogik ❌ Abhängigkeit von Basistabellen
✅ Abstraktion der Datenstruktur
View löschen

Views können natürlich auch wieder gelöscht werden mit folgendem Syntax:

DROP VIEW IF EXISTS verfuegbare_produkte;
DROP VIEW IF EXISTS bestelluebersicht;
Output
DROP VIEW
DROP VIEW

Stored Procedures & Functions

Stored Procedures (gespeicherte Prozeduren) und Functions sind vordefinierte SQL-Programme, die in der Datenbank gespeichert werden.

Die Unterschiede zwischen Prozeduren und Funktionen sind:

Eigenschaft Function Procedure
Rückgabewert Muss einen Wert zurückgeben Kein oder mehrere Werte
Verwendung In SELECT-Statements Mit CALL aufgerufen
Datenänderung Sollte keine Daten ändern Darf Daten ändern
Funktion für Produktverfügbarkeit
CREATE OR REPLACE FUNCTION ist_verfuegbar(p_produkt_id INTEGER, p_menge INTEGER)
RETURNS BOOLEAN AS $$
BEGIN
    RETURN EXISTS (
        SELECT 1
        FROM produkte
        WHERE produkt_id = p_produkt_id
          AND aktiv = TRUE
          AND lagerbestand >= p_menge
    );
END;
$$ LANGUAGE plpgsql;

Verwendung:

-- Prüfen, ob 10 Stück Laptop verfügbar sind
SELECT produktname, ist_verfuegbar(produkt_id, 10) AS verfuegbar
FROM produkte;
Output
      produktname      | verfuegbar
-----------------------+------------
 Laptop ThinkPad X1    | t
 Wireless Mouse MX3    | t
 USB-C Hub 7-Port      | t
 Monitor 27" 4K        | f
 Mechanische Tastatur  | t
 Webcam HD Pro         | f
 Laptop-Tasche Premium | t
(7 rows)
Procedure für Bestellung erstellen
CREATE OR REPLACE PROCEDURE erstelle_bestellung(
    p_kunde VARCHAR,
    p_produkt_id INTEGER,
    p_menge INTEGER
)
LANGUAGE plpgsql AS $$
DECLARE
    v_bestell_id INTEGER;
    v_preis NUMERIC;
BEGIN
    -- Preis holen
    SELECT preis INTO v_preis FROM produkte WHERE produkt_id = p_produkt_id;

    -- Bestellung erstellen
    INSERT INTO bestellungen (kunde, status, gesamtbetrag)
    VALUES (p_kunde, 'offen', v_preis * p_menge)
    RETURNING bestell_id INTO v_bestell_id;

    -- Bestellposition erstellen
    INSERT INTO bestellpositionen (bestell_id, produkt_id, menge, einzelpreis)
    VALUES (v_bestell_id, p_produkt_id, p_menge, v_preis);

    -- Lagerbestand reduzieren
    UPDATE produkte
    SET lagerbestand = lagerbestand - p_menge
    WHERE produkt_id = p_produkt_id;

    RAISE NOTICE 'Bestellung % fuer Kunde % erstellt', v_bestell_id, p_kunde;
END;
$$;

Verwendung:

CALL erstelle_bestellung('Max Mustermann', 1, 2);
Output
HINWEIS:  Bestellung 4 fuer Kunde Max Mustermann erstellt

Trigger

Ein Trigger ist ein automatisch ausgeführtes SQL-Programm, das bei bestimmten Ereignissen (INSERT, UPDATE, DELETE) aktiviert wird.

Typische Anwendungsfälle sind:

  • Automatische Protokollierung von Änderungen
  • Datenkonsistenz durch automatische Updates
  • Durchsetzung von Geschäftsregeln
  • Audit-Trails und Logging
Automatische Zeitstempel-Aktualisierung
-- Trigger-Function erstellen
CREATE OR REPLACE FUNCTION update_timestamp()
RETURNS TRIGGER AS $$
BEGIN
    NEW.letzte_aenderung = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Trigger erstellen
CREATE TRIGGER produkt_update_timestamp
BEFORE UPDATE ON produkte
FOR EACH ROW
EXECUTE FUNCTION update_timestamp();

Wirkung: Jedes Mal, wenn ein Produkt geändert wird, wird automatisch letzte_aenderung aktualisiert.

-- Produkt aktualisieren
UPDATE produkte SET preis = 1199.99 WHERE produkt_id = 1;

-- Zeitstempel wurde automatisch gesetzt
SELECT produktname, preis, letzte_aenderung FROM produkte WHERE produkt_id = 1;
Output
    produktname     |  preis  |      letzte_aenderung
--------------------+---------+----------------------------
 Laptop ThinkPad X1 | 1199.99 | 2025-11-26 09:55:40.404667
(1 row)
weitere Beispiele

Ein praktischeres Beispiel: Lagerbestand automatisch reduzieren, wenn eine Bestellposition erstellt wird.

-- Trigger-Function erstellen
CREATE OR REPLACE FUNCTION reduziere_lagerbestand()
RETURNS TRIGGER AS $$
BEGIN
    UPDATE produkte
    SET lagerbestand = lagerbestand - NEW.menge
    WHERE produkt_id = NEW.produkt_id;

    -- Warnung, wenn Lagerbestand niedrig wird
    IF (SELECT lagerbestand FROM produkte WHERE produkt_id = NEW.produkt_id) < 5 THEN
        RAISE NOTICE 'Warnung: Niedriger Lagerbestand fuer Produkt %', NEW.produkt_id;
    END IF;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Trigger erstellen
CREATE TRIGGER nach_bestellposition_einfuegen
AFTER INSERT ON bestellpositionen
FOR EACH ROW
EXECUTE FUNCTION reduziere_lagerbestand();

Wirkung: Bei jeder neuen Bestellposition wird automatisch der Lagerbestand reduziert.

-- Vor der Bestellung
SELECT produktname, lagerbestand FROM produkte WHERE produkt_id = 4;
Output
  produktname   | lagerbestand
----------------+--------------
 Monitor 27" 4K |            8
(1 row)
-- Neue Bestellung erstellen
INSERT INTO bestellungen (kunde, status) VALUES ('Peter Klein', 'offen');
INSERT INTO bestellpositionen (bestell_id, produkt_id, menge, einzelpreis)
VALUES (4, 4, 4, 449.99);

-- Nach der Bestellung
SELECT produktname, lagerbestand FROM produkte WHERE produkt_id = 4;
Output
HINWEIS:  Warnung: Niedriger Lagerbestand fuer Produkt 4

  produktname   | lagerbestand
----------------+--------------
 Monitor 27" 4K |            5
(1 row)

Typische Befehle im Zusammen hang mit Trigger sind:

Typ Zeitpunkt Verwendung
BEFORE Vor der Operation Daten noch ändern/validieren
AFTER Nach der Operation Logging, Benachrichtigungen
FOR EACH ROW Für jede Zeile Zeilen-spezifische Logik
FOR EACH STATEMENT Einmal pro Statement Statement-Level Logging

JSON-Support in PostgreSQL

PostgreSQL bietet native Unterstützung für JSON-Daten, was flexible, semi-strukturierte Datenspeicherung ermöglicht.

Typ Speicherung Performance
JSON Als Text Langsamer
JSONB Binär (komprimiert) Schneller (empfohlen ✅)
Produkte mit flexiblen Attributen
CREATE TABLE produkte_extended (
    produkt_id SERIAL PRIMARY KEY,
    produktname VARCHAR(200) NOT NULL,
    kategorie VARCHAR(100),
    preis NUMERIC(10, 2) NOT NULL,
    attribute JSONB  -- Flexible zusätzliche Produkteigenschaften
);

INSERT INTO produkte_extended (produktname, kategorie, preis, attribute) VALUES
('Laptop ThinkPad X1', 'Elektronik', 1299.99,
 '{"bildschirm": "14 Zoll", "prozessor": "Intel i7", "ram_gb": 16, "ssd_gb": 512, "farben": ["Schwarz", "Silber"]}'::jsonb),
('Wireless Mouse MX3', 'Zubehör', 79.99,
 '{"dpi": 4000, "kabellos": true, "batterielaufzeit_tage": 70, "farben": ["Schwarz", "Weiß", "Grau"]}'::jsonb),
('Monitor 27" 4K', 'Elektronik', 449.99,
 '{"aufloesung": "3840x2160", "bildwiederholrate_hz": 60, "panel_typ": "IPS", "hdr": true}'::jsonb);

JSON-Abfragen:

-- Zugriff auf JSON-Felder
SELECT produktname, attribute->>'bildschirm' AS bildschirm, attribute->>'prozessor' AS prozessor
FROM produkte_extended
WHERE attribute ? 'bildschirm';  -- Nur Produkte mit Bildschirm-Attribut
Output
    produktname     | bildschirm | prozessor
--------------------+------------+-----------
 Laptop ThinkPad X1 | 14 Zoll    | Intel i7
(1 row)
-- Nach JSON-Werten filtern
SELECT produktname, attribute->>'ram_gb' AS ram
FROM produkte_extended
WHERE (attribute->>'ram_gb')::integer >= 16;
Output
    produktname     | ram
--------------------+-----
 Laptop ThinkPad X1 | 16
(1 row)
-- JSON-Array durchsuchen
SELECT produktname, attribute->'farben' AS verfuegbare_farben
FROM produkte_extended
WHERE attribute->'farben' ? 'Schwarz';  -- Produkte in Schwarz
Output
    produktname     |     verfuegbare_farben
--------------------+-----------------------------
 Laptop ThinkPad X1 | ["Schwarz", "Silber"]
 Wireless Mouse MX3 | ["Schwarz", "Weiß", "Grau"]
(2 rows)
Wann JSON verwenden?

Vorteile:

  • ✅ Flexibel für unterschiedliche Datenstrukturen
  • ✅ Keine Schema-Änderungen nötig
  • ✅ Ideal für externe APIs und Logs

Nachteile:

  • ❌ Weniger performant als normale Spalten
  • ❌ Schwieriger zu normalisieren
  • ❌ Integritätsprüfungen komplizierter

Faustregel: Verwende JSON für optionale, flexible Daten, aber nicht für kritische Geschäftslogik.

So accurate..!!😓
byu/Abhi_mech007 inProgrammerHumor

Backup & Recovery

Datenbanken speichern oft geschäftskritische Daten. Bei Hardware-Ausfällen, Software-Fehlern oder menschlichen Fehlern ist ein Backup essentiell.

Typische PostgreSQL Backup-Methoden sind:

Methode Beschreibung Anwendungsfall
pg_dump Logisches Backup (SQL-Export) Einzelne Datenbank, portabel
pg_dumpall Alle Datenbanken Kompletter Server-Export
Physisches Backup Dateisystem-Level Kopie Große Datenbanken, schnell
Backup mit pg_dump verwenden

Folgende Befehle müssen im Terminal (macOS) oder in der Powershell/CMD (Windows) eingegeben werden. Port (hier 5433) und Server (hier localhost) müssen gegebenenfalls angepasst werden.

Gesamte Datenbank sichern:

pg_dump -h localhost -p 5433 -U postgres shop_db > shop_db_backup.sql

Nur Struktur (ohne Daten):

pg_dump -h localhost -p 5433 -U postgres --schema-only shop_db > struktur.sql

Nur Daten (ohne Struktur):

pg_dump -h localhost -p 5433 -U postgres --data-only shop_db > daten.sql

Bestimmte Tabelle sichern:

pg_dump -h localhost -p 5433 -U postgres -t produkte shop_db > produkte_backup.sql

Wiederherstellen:

psql -h localhost -p 5433 -U postgres shop_db < shop_db_backup.sql

Zusammenfassung 📌

In diesem Kapitel haben wir einen Ausblick auf weiterführende Datenbankthemen erhalten:

  • Views – Virtuelle Tabellen für vereinfachte Abfragen
  • Stored Procedures & Functions – Wiederverwendbare SQL-Programme
  • Trigger – Automatische Aktionen bei Datenänderungen
  • JSON-Support – Flexible, semi-strukturierte Daten
  • Backup & Recovery – Datensicherung und -wiederherstellung

Abschließende Gedanken 🎉

Datenbanken sind das Herzstück fast jeder modernen Anwendung. Egal ob Web-App, Mobile-App, Desktop-Software oder Data Science – überall werden Daten gespeichert, verwaltet und analysiert.

Das relationale Modell mit SQL ist seit über 50 Jahren der Standard und wird auch in absehbarer Zukunft wichtig bleiben. Die Konzepte, die du gelernt hast – Normalisierung, Beziehungen, Joins, Transaktionen – sind universell anwendbar und werden dich in deiner gesamten IT-Karriere begleiten.


Glückwunsch! 🎉

Du hast das Ende dieses Kurses erreicht und alle wichtigen Grundlagen zu Datenbanken und SQL gelernt!

Das hast du gemeistert:

  • ✅ Datenmodellierung und ER-Diagramme
  • ✅ SQL-Grundlagen (SELECT, INSERT, UPDATE, DELETE)
  • ✅ Komplexe Abfragen mit Joins und Aggregationen
  • ✅ Datenintegrität mit Constraints
  • ✅ Transaktionen und ACID-Prinzipien
  • ✅ Fortgeschrittene Konzepte und Ausblick

Nutze dieses Wissen als Startpunkt für deine eigenen Datenbankprojekte!

Viel Erfolg auf deiner Reise in die Welt der Datenbanken! 🚀


Ende des Kurses – Aber nicht des Lernens!