Zum Inhalt

M165 NoSQL Datenbanken | Block 02

Inhaltsverzeichnis

Modellierungsübung Online-Bestellsystem

Normalisierung

Modellierungsübung Online-Bestellsystem

Aufgabe Moodle

erDiagram

    %% ============================
    %% ENTITAETEN
    %% ============================

    KUNDE {
        int Kunden_ID PK
        string Vorname
        string Nachname
        string Email "UNIQUE"
        string Passwort
        string Telefonnummer
        string Adresse
    }

    PRODUKT {
        int Produkt_ID PK
        string Produktname
        string Beschreibung
        double Preis
        int Lagerbestand
    }

    BESTELLUNG {
        int Bestell_ID PK
        int Kunden_ID FK
        date Bestelldatum
        string Status
    }

    BESTELLPOSITION {
        int Bestellpositions_ID PK
        int Bestell_ID FK
        int Produkt_ID FK
        int Menge
    }

    %% ============================
    %% BEZIEHUNGEN
    %% ============================

    %% KUNDE (1) --- (n) BESTELLUNG
    KUNDE ||--o{ BESTELLUNG : "gibt auf"

    %% BESTELLUNG (1) --- (n) BESTELLPOSITION
    BESTELLUNG ||--o{ BESTELLPOSITION : "enthält"

    %% PRODUKT (1) --- (n) BESTELLPOSITION
    %% bildet gemeinsam eine n:m Beziehung
    PRODUKT ||--o{ BESTELLPOSITION : "kommt vor in"

Normalisierung

Ausgangstabelle (unnormalisiert)

Film_ID Titel Jahr Regisseur Regisseur_Telefon Hauptdarsteller Genre
1 Der Pate 1972 Francis Ford Coppola +430123-456789 Marlon Brando, Al Pacino Drama, Krimi
2 Inception zweitausendzehn Christopher Nolan 0041 0987-654321 Leonardo DiCaprio Sci-Fi, Thriller
3 Pulp Fiction 1994 Quentin Tarantino 0456789012 John Travolta, Uma Thurman Drama, Krimi
4 Titanic 1997 James Cameron 0123-456789 Leonardo DiCaprio, Kate Winslet Drama, Romantik
5 The Dark Knight zweitausendacht Christopher Nolan 0987-654321 Christian Bale, Heath Ledger Action, Drama

1. Normalform (1NF)

Ziele

  • Keine mehrfachen Werte

  • Jedes Feld atomar

  • Einheitliche Formate

Probleme

  • Hauptdarsteller enthält Listen

  • Genre enthält Listen

  • Jahr ist uneinheitlich (Zahl / Wort)

Lösung

  • Schauspieler → eigene Tabelle

  • Genres → eigene Tabelle

  • Jahr → überall Integer


Normalform (2NF)

Ziele

  • Alle Nicht-Schlüsselattribute hängen vom ganzen Primärschlüssel ab

Erkenntnisse

  • Ein Regisseur kann mehrere Filme machen → Auslagern

  • Regisseur_Telefon gehört funktional zum Regisseur → Auslagern

Neue Tabellen

  • REGISSEUR

  • FILM_SCHAUSPIELER (m:n)

  • FILM_GENRE (m:n)


3. Normalform (3NF)

Ziel

  • Keine transitiven Abhängigkeiten

Korrektes Modell

  • Telefon hängt vom Regisseur ab → separate Tabelle REGISSEUR

  • Keine Nicht-Schlüsselattribute hängen voneinander ab


Finale normalisierte Tabellenstruktur

Tabelle: FILM

Attribut Typ Beschreibung
Film_ID (PK) INT eindeutige ID
Titel VARCHAR Filmtitel
Jahr INT Erscheinungsjahr
Regisseur_ID (FK) INT Verweis auf Regisseur

Tabelle: REGISSEUR

Attribut Typ
Regisseur_ID (PK) INT
Name VARCHAR
Telefon VARCHAR

Tabelle: SCHAUSPIELER

Attribut Typ
Schauspieler_ID (PK) INT
Name VARCHAR

Tabelle: FILM_SCHAUSPIELER (m:n Beziehung)

Attribut Typ
Film_ID (FK) INT
Schauspieler_ID (FK) INT

Tabelle: GENRE

Attribut Typ
Genre_ID (PK) INT
Genre_Name VARCHAR

Tabelle: FILM_GENRE (m:n Beziehung)

Attribut Typ
Film_ID (FK) INT
Genre_ID (FK) INT

Mermaid ER-Diagramm (konzeptionelles Modell)

erDiagram

    FILM {
        int Film_ID PK
        string Titel
        int Jahr
        int Regisseur_ID FK
    }

    REGISSEUR {
        int Regisseur_ID PK
        string Name
        string Telefon
    }

    SCHAUSPIELER {
        int Schauspieler_ID PK
        string Name
    }

    GENRE {
        int Genre_ID PK
        string Genre_Name
    }

    FILM_SCHAUSPIELER {
        int Film_ID FK
        int Schauspieler_ID FK
    }

    FILM_GENRE {
        int Film_ID FK
        int Genre_ID FK
    }

    REGISSEUR ||--o{ FILM : "führt"
    FILM ||--o{ FILM_SCHAUSPIELER : ""
    SCHAUSPIELER ||--o{ FILM_SCHAUSPIELER : ""
    FILM ||--o{ FILM_GENRE : ""
    GENRE ||--o{ FILM_GENRE : ""
Erklärung Beziehungen
Pfeil / Symbol Bedeutung Erklärung
|| genau 1 Ein Objekt muss genau einmal vorkommen
o| 0 oder 1 Optional: kann vorkommen, muss aber nicht
|{ 1 zu viele Eine Entität ist mit vielen anderen verbunden
o{ 0 bis viele Optional viele: kann mit mehreren verbunden sein
-- einfache Beziehung Verbindung ohne definierte Kardinalität
||--o{ 1 zu 0..n Ein Objekt hat viele, aber die Gegenseite ist optional
o{--o{ n zu n Viele-zu-Viele-Beziehung
||--|| 1 zu 1 Beide Seiten kommen genau einmal vor

SQL-Abfragen

Alle Abfragen

Hier die Abfragen:

Microsoft Windows [Version 10.0.22631.6060]
(c) Microsoft Corporation. Alle Rechte vorbehalten.

C:\windows\System32>mysql -u root -p
Enter password: ********
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.40 MySQL Community Server - GPL

Copyright (c) 2000, 2024, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> CREATE DATABASE FilmDB;
Query OK, 1 row affected (0.04 sec)

mysql> USE FilmDB
Database changed
mysql> CREATE TABLE Regisseur (
    -> Regisseur_ID INT PRIMARY KEY,
    -> Name VARCHAR(100),
    -> Telefon VARCHAR(30)
    -> );
Query OK, 0 rows affected (0.06 sec)

mysql> SHOW TABLES;
+------------------+
| Tables_in_filmdb |
+------------------+
| regisseur        |
+------------------+
1 row in set (0.04 sec)

mysql> SHOW regisseur
    -> ^Z^C
mysql> CREATE TABLE Film (
    ->     Film_ID INT PRIMARY KEY,
    ->     Titel VARCHAR(100),
    ->     Jahr INT,
    ->     Regisseur_ID INT,
    ->     FOREIGN KEY (Regisseur_ID) REFERENCES Regisseur(Regisseur_ID)
    -> );
Query OK, 0 rows affected (0.06 sec)

mysql>
mysql> CREATE TABLE Hauptdarsteller (
    ->     Hauptdarsteller_ID INT PRIMARY KEY,
    ->     Film_ID INT,
    ->     Hauptdarsteller VARCHAR(100),
    ->     FOREIGN KEY (Film_ID) REFERENCES Film(Film_ID)
    -> );
Query OK, 0 rows affected (0.06 sec)

mysql>
mysql> CREATE TABLE Genre (
    ->     Genre_ID INT PRIMARY KEY,
    ->     Film_ID INT,
    ->     Genre VARCHAR(50),
    ->     FOREIGN KEY (Film_ID) REFERENCES Film(Film_ID)
    -> );
Query OK, 0 rows affected (0.06 sec)

mysql> SHOW TABLES;
+------------------+
| Tables_in_filmdb |
+------------------+
| film             |
| genre            |
| hauptdarsteller  |
| regisseur        |
+------------------+
4 rows in set (0.00 sec)

mysql> INSERT INTO Regisseur VALUES
    -> (1, 'Francis Ford Coppola', '0123-456789'),
    -> (2, 'Christopher Nolan', '0987-654321'),
    -> (3, 'Quentin Tarantino', '0456-789012'),
    -> (4, 'James Cameron', '0123-456789');
Query OK, 4 rows affected (0.02 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> INSERT INTO Film VALUES
    -> (1, 'Der Pate', 1972, 1),
    -> (2, 'Inception', 2010, 2),
    -> (3, 'Pulp Fiction', 1994, 3),
    -> (4, 'Titanic', 1997, 4),
    -> (5, 'The Dark Knight', 2008, 2);
Query OK, 5 rows affected (0.03 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> INSERT INTO Hauptdarsteller VALUES
    -> (1, 1, 'Marlon Brando'),
    -> (2, 1, 'Al Pacino'),
    -> (3, 2, 'Leonardo DiCaprio'),
    -> (4, 3, 'John Travolta'),
    -> (5, 3, 'Uma Thurman'),
    -> (6, 4, 'Leonardo DiCaprio'),
    -> (7, 4, 'Kate Winslet'),
    -> (8, 5, 'Christian Bale'),
    -> (9, 5, 'Heath Ledger');
Query OK, 9 rows affected (0.01 sec)
Records: 9  Duplicates: 0  Warnings: 0

mysql> INSERT INTO Genre VALUES
    -> (1, 1, 'Drama'),
    -> (2, 1, 'Krimi'),
    -> (3, 2, 'Sci-Fi'),
    -> (4, 2, 'Thriller'),
    -> (5, 3, 'Drama'),
    -> (6, 3, 'Krimi'),
    -> (7, 4, 'Drama'),
    -> (8, 4, 'Romantik'),
    -> (9, 5, 'Action'),
    -> (10, 5, 'Drama');
Query OK, 10 rows affected (0.01 sec)
Records: 10  Duplicates: 0  Warnings: 0

mysql> SELECT Film.Titel
    -> FROM Film
    -> JOIN Regisseur ON Film.Regisseur_ID = Regisseur.Regisseur_ID
    -> WHERE Regisseur.Name = 'Christopher Nolan';
+-----------------+
| Titel           |
+-----------------+
| Inception       |
| The Dark Knight |
+-----------------+
2 rows in set (0.01 sec)

mysql> SELECT Regisseur.Name, COUNT(Film.Film_ID) AS AnzahlFilme
    -> FROM Regisseur
    -> LEFT JOIN Film ON Film.Regisseur_ID = Regisseur.Regisseur_ID
    -> GROUP BY Regisseur.Name;
+----------------------+-------------+
| Name                 | AnzahlFilme |
+----------------------+-------------+
| Francis Ford Coppola |           1 |
| Christopher Nolan    |           2 |
| Quentin Tarantino    |           1 |
| James Cameron        |           1 |
+----------------------+-------------+
4 rows in set (0.01 sec)

mysql> SELECT Film.Titel, COUNT(Genre.Genre_ID) AS AnzahlGenres
    -> FROM Film
    -> JOIN Genre ON Film.Film_ID = Genre.Film_ID
    -> GROUP BY Film.Film_ID
    -> HAVING COUNT(Genre.Genre_ID) > 1;
+-----------------+--------------+
| Titel           | AnzahlGenres |
+-----------------+--------------+
| Der Pate        |            2 |
| Inception       |            2 |
| Pulp Fiction    |            2 |
| Titanic         |            2 |
| The Dark Knight |            2 |
+-----------------+--------------+
5 rows in set (0.01 sec)

mysql> SELECT Film.Titel, Hauptdarsteller.Hauptdarsteller
    -> FROM Hauptdarsteller
    -> JOIN Film ON Film.Film_ID = Hauptdarsteller.Film_ID
    -> ORDER BY Film.Titel;
+-----------------+-------------------+
| Titel           | Hauptdarsteller   |
+-----------------+-------------------+
| Der Pate        | Marlon Brando     |
| Der Pate        | Al Pacino         |
| Inception       | Leonardo DiCaprio |
| Pulp Fiction    | John Travolta     |
| Pulp Fiction    | Uma Thurman       |
| The Dark Knight | Christian Bale    |
| The Dark Knight | Heath Ledger      |
| Titanic         | Leonardo DiCaprio |
| Titanic         | Kate Winslet      |
+-----------------+-------------------+
9 rows in set (0.01 sec)

mysql> SELECT Film.Titel, Regisseur.Name
    -> FROM Film
    -> JOIN Regisseur ON Film.Regisseur_ID = Regisseur.Regisseur_ID
    -> WHERE Film.Jahr = 1994;
+--------------+-------------------+
| Titel        | Name              |
+--------------+-------------------+
| Pulp Fiction | Quentin Tarantino |
+--------------+-------------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM Regisseur;
+--------------+----------------------+-------------+
| Regisseur_ID | Name                 | Telefon     |
+--------------+----------------------+-------------+
|            1 | Francis Ford Coppola | 0123-456789 |
|            2 | Christopher Nolan    | 0987-654321 |
|            3 | Quentin Tarantino    | 0456-789012 |
|            4 | James Cameron        | 0123-456789 |
+--------------+----------------------+-------------+
4 rows in set (0.01 sec)

mysql> SELECT Name, Telefon
    -> FROM Regisseur
    -> WHERE Telefon LIKE '0123%';
+----------------------+-------------+
| Name                 | Telefon     |
+----------------------+-------------+
| Francis Ford Coppola | 0123-456789 |
| James Cameron        | 0123-456789 |
+----------------------+-------------+
2 rows in set (0.01 sec)

mysql> SELECT Film.Titel, Genre.Genre
    -> FROM Film
    -> JOIN Genre ON Film.Film_ID = Genre.Film_ID
    -> ORDER BY Film.Titel;
+-----------------+----------+
| Titel           | Genre    |
+-----------------+----------+
| Der Pate        | Drama    |
| Der Pate        | Krimi    |
| Inception       | Sci-Fi   |
| Inception       | Thriller |
| Pulp Fiction    | Drama    |
| Pulp Fiction    | Krimi    |
| The Dark Knight | Action   |
| The Dark Knight | Drama    |
| Titanic         | Drama    |
| Titanic         | Romantik |
+-----------------+----------+
10 rows in set (0.00 sec)

mysql> SELECT Film.Titel, Genre.Genre
    -> FROM Film
    -> JOIN Genre ON Film.Film_ID = Genre.Film_ID
    -> ORDER BY Film.Genre;
ERROR 1054 (42S22): Unknown column 'Film.Genre' in 'order clause'
mysql> SELECT * FROM Film;
+---------+-----------------+------+--------------+
| Film_ID | Titel           | Jahr | Regisseur_ID |
+---------+-----------------+------+--------------+
|       1 | Der Pate        | 1972 |            1 |
|       2 | Inception       | 2010 |            2 |
|       3 | Pulp Fiction    | 1994 |            3 |
|       4 | Titanic         | 1997 |            4 |
|       5 | The Dark Knight | 2008 |            2 |
+---------+-----------------+------+--------------+
5 rows in set (0.00 sec)

mysql>

Rollenkonzept

Das Rollenkonzept (Role-Based Access Control, RBAC) dient dazu, Berechtigungen effizient und sicher zu verwalten:

  • Funktionsweise: Berechtigungen (z. B. Lesen, Schreiben, Löschen) werden nicht direkt einzelnen Benutzern zugewiesen, sondern an Rollen (z. B. „Buchhaltung“, „Administrator“, „Praktikant“) gebunden. Benutzer werden dann diesen Rollen zugeordnet.

  • Vorteile:

  • Übersichtlichkeit: Einfachere Verwaltung bei vielen Nutzern.

  • Sicherheit (Least Privilege): Nutzer erhalten nur die Rechte, die sie für ihre spezifische Rolle wirklich benötigen.

  • Flexibilität: Verlässt ein Mitarbeiter das Unternehmen, muss nur sein Account gelöscht werden; die Rolle bleibt für den Nachfolger bestehen.

Datensicherheit

Ein Datensicherheitskonzept beschreibt technische und organisatorische Massnahmen zum Schutz von Daten vor Verlust, Manipulation oder unberechtigtem Zugriff.

Mögliche Konsequenzen bei Nichteinhaltung:

  • Rechtlich: Hohe Bussgelder (z. B. durch die DSGVO bis zu 4 % des weltweiten Jahresumsatzes).

  • Finanziell: Kosten für Schadensbegrenzung, Systemwiederherstellung oder Lösegelder bei Ransomware-Angriffen.

  • Reputation: Vertrauensverlust bei Kunden und Partnern, was zu Geschäftsaufgaben führen kann.

  • Betrieblich: Stillstand der Produktion oder des Dienstleistungsbetriebs durch Datenverlust.

Aufgabe 1: Alle Filme eines bestimmten Regisseurs abrufen

Frage: Zeigen Sie alle Filme, die von "Christopher Nolan" inszeniert wurden.

SELECT Film.Titel
FROM Film
JOIN Regisseur ON Film.Regisseur_ID = Regisseur.Regisseur_ID
WHERE Regisseur.Name = 'Christopher Nolan';

Aufgabe 2: Anzahl der Filme pro Regisseur

Frage: Ermitteln Sie die Anzahl der Filme, die jeder Regisseur in der Datenbank inszeniert hat.

SELECT Regisseur.Name, COUNT(Film.Film_ID) AS AnzahlFilme
FROM Regisseur
LEFT JOIN Film ON Film.Regisseur_ID = Regisseur.Regisseur_ID
GROUP BY Regisseur.Name;

Aufgabe 3: Filme mit mehreren Genres

Frage: Listen Sie alle Filme auf, die mehr als ein Genre haben. Geben Sie den Titel des Films und die Anzahl der Genres an.

SELECT Film.Titel, COUNT(Genre.Genre_ID) AS AnzahlGenres
FROM Film
JOIN Genre ON Film.Film_ID = Genre.Film_ID
GROUP BY Film.Film_ID
HAVING COUNT(Genre.Genre_ID) > 1;

Aufgabe 4: Hauptdarsteller nach Film sortiert

Frage: Zeigen Sie alle Hauptdarsteller zusammen mit dem Titel des Films, in dem sie mitspielen, und sortieren Sie das Ergebnis nach Film.

SELECT Film.Titel, Hauptdarsteller.Hauptdarsteller
FROM Hauptdarsteller
JOIN Film ON Film.Film_ID = Hauptdarsteller.Film_ID
ORDER BY Film.Titel;

Aufgabe 5: Filme aus einem bestimmten Jahr

Frage: Finden Sie alle Filme, die im Jahr 1994 veröffentlicht wurden, und geben Sie den Titel und den Regisseur an.

SELECT Film.Titel, Regisseur.Name
FROM Film
JOIN Regisseur ON Film.Regisseur_ID = Regisseur.Regisseur_ID
WHERE Film.Jahr = 1994;

Aufgabe 6: Regisseure mit Kontaktinformationen

Frage: Listen Sie alle Regisseure auf, deren Telefonnummer mit "0123" beginnt, und geben Sie deren Namen und Telefonnummer an.

SELECT Name, Telefon
FROM Regisseur
WHERE Telefon LIKE '0123%';

Aufgabe 7: Filme und deren Genres

Frage: Zeigen Sie alle Filme zusammen mit ihren Genres an. Geben Sie den Titel des Films und das Genre aus.

SELECT Film.Titel, Genre.Genre
FROM Film
JOIN Genre ON Film.Film_ID = Genre.Film_ID
ORDER BY Film.Titel;

NewSQL vs NoSQL

NewSQL ist ein moderner Ansatz, der versucht, die Vorteile beider Welten zu vereinen:

  • Herkömmliche Relationale Datenbanken (SQL): Fokus auf ACID-Konformität (Datenkonsistenz) und komplexe Abfragen, stoßen aber bei der Skalierbarkeit an Grenzen (meist nur vertikal).

  • NoSQL: Fokus auf horizontale Skalierbarkeit und Flexibilität für unstrukturierte Daten, opfert dafür oft die sofortige Konsistenz (BASE-Prinzip).

  • NewSQL: Kombiniert die ACID-Garantien und die SQL-Abfragesprache der relationalen Systeme mit der horizontalen Skalierbarkeit von NoSQL. Sie sind ideal für Anwendungen, die sowohl hohe Transaktionsraten als auch absolute Datengenauigkeit erfordern.