Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
| de:modul:m290_guko:learningunits:lu08:theorie:c_fk-create-table [2026/08/13 16:06] – gelöscht - Externe Bearbeitung (Unbekanntes Datum) 127.0.0.1 | de:modul:m290_guko:learningunits:lu08:theorie:c_fk-create-table [2026/08/13 16:06] (aktuell) – ↷ Links angepasst, weil Seiten im Wiki verschoben wurden 216.73.216.62 | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| + | ====== LU08c: Tabellen mit Fremdschlüssel erstellen ====== | ||
| + | |||
| + | **Ziel:** Wir verteilen die Daten wie bei WordPress auf mehrere Tabellen (**users**, **posts**, **categories** und die N: | ||
| + | |||
| + | ==== ERD (Überblick) ==== | ||
| + | Wir gehen vom Schema aus dem Reiseblog-Beispiel aus: | ||
| + | |||
| + | {{ de: | ||
| + | |||
| + | <WRAP tip round 80% center> | ||
| + | Posts können mehreren Kategorien angehören (N:M). Die saubere Lösung ist eine Zwischentabelle '' | ||
| + | Das bauen wir später (s. LU08e: N: | ||
| + | </ | ||
| + | |||
| + | |||
| + | ===== Fremdschlüssel: | ||
| + | <WRAP center tip round 80%> | ||
| + | [[https:// | ||
| + | </ | ||
| + | |||
| + | <WRAP box round center 80%> | ||
| + | <code sql> | ||
| + | CREATE TABLE table_name ( | ||
| + | id INT AUTO_INCREMENT PRIMARY KEY, | ||
| + | foreign_key_col | ||
| + | FOREIGN KEY (foreign_key_col) REFERENCES parent_table(parent_pk) | ||
| + | ); | ||
| + | </ | ||
| + | **Wichtig: | ||
| + | </ | ||
| + | |||
| + | ===== Beispiel Reiseblog ===== | ||
| + | |||
| + | <WRAP center tip round 80%> | ||
| + | [[https:// | ||
| + | </ | ||
| + | |||
| + | ==== 1. Tabellen anlegen ==== | ||
| + | |||
| + | <WRAP box round center 80%> | ||
| + | === Tabelle users === | ||
| + | <code sql> | ||
| + | CREATE TABLE users ( | ||
| + | user_id | ||
| + | username | ||
| + | email | ||
| + | display_name | ||
| + | registered_at DATETIME | ||
| + | ); | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <WRAP box round center 80%> | ||
| + | === Tabelle posts === | ||
| + | <code sql> | ||
| + | CREATE TABLE posts ( | ||
| + | post_id | ||
| + | title VARCHAR(200) NOT NULL, | ||
| + | featured_img | ||
| + | content | ||
| + | created_at | ||
| + | author_id | ||
| + | FOREIGN KEY (author_id) REFERENCES users (user_id) -- Foreign Key wird hier angelegt! | ||
| + | ); | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <WRAP box round center 80%> | ||
| + | === Tabelle categories === | ||
| + | <code sql> | ||
| + | CREATE TABLE categories ( | ||
| + | category_id INT AUTO_INCREMENT PRIMARY KEY, | ||
| + | name VARCHAR(100) NOT NULL, | ||
| + | slug VARCHAR(120) NOT NULL UNIQUE | ||
| + | ); | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== 2. Beispieldaten einfügen ==== | ||
| + | //Für ausführliche Erklärung zum Einfügen von Daten in Tabellen via SQL schauen Sie in "LU07 - DML: Daten einfügen, ändern und löschen" | ||
| + | |||
| + | <WRAP center box 80% round>< | ||
| + | -- 1) Autor:innen | ||
| + | INSERT INTO users (username, email, display_name) VALUES | ||
| + | (' | ||
| + | (' | ||
| + | (' | ||
| + | |||
| + | -- 2) Kategorien | ||
| + | INSERT INTO categories (name, slug) VALUES | ||
| + | (' | ||
| + | (' | ||
| + | (' | ||
| + | (' | ||
| + | (' | ||
| + | (' | ||
| + | (' | ||
| + | (' | ||
| + | (' | ||
| + | (' | ||
| + | |||
| + | -- 3) Posts | ||
| + | INSERT INTO posts (title, featured_img, | ||
| + | (' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | |||
| + | (' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | |||
| + | (' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | |||
| + | (' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | |||
| + | (' | ||
| + | ' | ||
| + | 'Bucht von Kotor, Durmitor, Tara-Schlucht …', | ||
| + | ' | ||
| + | |||
| + | ('Oman – Top 22 Highlights', | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | |||
| + | (' | ||
| + | ' | ||
| + | ' | ||
| + | ' | ||
| + | |||
| + | </ | ||
| + | |||
| + | **Resultate (nach dem Einfügen): | ||
| + | |||
| + | === Verknüpfung Tabelle users & posts (one-to-many) === | ||
| + | |||
| + | {{de: | ||
| + | |||
| + | === Tabelle categories (wird später mit ' | ||
| + | |||
| + | {{de: | ||
| + | |||
| + | ==== 3. Fremdschlüssel in Aktion (Standard: RESTRICT) ==== | ||
| + | Beim Setzen von Fremdschlüsseln überwacht MySQL/ | ||
| + | |||
| + | Bezogen auf unser Reiseblog-Beispiel: | ||
| + | Damit ist //users// die Elterntabelle und //posts// die Kindtabelle. Die Folge von '' | ||
| + | |||
| + | * Löschen eines Users ist blockiert, solange Posts auf diesen User verweisen. | ||
| + | * Ändern von '' | ||
| + | * Änderungen an nicht referenzierten Spalten (z. B. '' | ||
| + | |||
| + | Probieren Sie folgende Codesnippets in Webstorm/ | ||
| + | |||
| + | === Demo 1 – User ohne Posts löschen (erlaubt) === | ||
| + | <WRAP center box 80% round>< | ||
| + | DELETE FROM users | ||
| + | WHERE username = ' | ||
| + | SELECT user_id, username FROM users; | ||
| + | </ | ||
| + | // | ||
| + | |||
| + | === Demo 2 – User mit Posts löschen (blockiert) === | ||
| + | <WRAP center box 80% round>< | ||
| + | DELETE FROM users | ||
| + | WHERE username = ' | ||
| + | </ | ||
| + | //Erwartete Fehlermeldung (sinngemäss):// | ||
| + | <WRAP alert round 80% center> | ||
| + | [23000][1451] Cannot delete or update a parent row: a foreign key constraint fails | ||
| + | (travel_blog.posts, | ||
| + | </ | ||
| + | //Grund: In posts.author_id gibt es Kindzeilen (z.B. " | ||
| + | |||
| + | === Demo 3 – Unkritisches Attribut ändern (erlaubt) === | ||
| + | <WRAP center box 80% round>< | ||
| + | UPDATE users | ||
| + | SET username = ' | ||
| + | WHERE user_id = 2; -- OK: FKs verweisen auf user_id, nicht auf username | ||
| + | </ | ||
| + | |||
| + | === Demo 4 – Primärschlüssel ändern (blockiert) === | ||
| + | <WRAP center box 80% round>< | ||
| + | UPDATE users | ||
| + | SET user_id = 5 | ||
| + | WHERE user_id = 2; -- erwartet: Fehler (RESTRICT), da posts.author_id -> users.user_id | ||
| + | </ | ||
| + | // | ||
| + | |||
| + | === Demo 5 – Primärschlüssel ändern: Geht das? (ja) === | ||
| + | <WRAP center box 80% round>< | ||
| + | UPDATE categories | ||
| + | SET category_id = 11 | ||
| + | WHERE category_id = 10; -- USA → 11: funktioniert - Primary Keys dürfen geändert werden. | ||
| + | </ | ||
| + | |||
| + | === Warum ist das so? === | ||
| + | |||
| + | // | ||
| + | |||
| + | Änderungen an nicht referenzierten Spalten (z. B. '' | ||
| + | |||
| + | Ob eine Änderung blockiert oder mitgezogen (CASCADE) wird, hängt von der ON DELETE/ON UPDATE-Einstellung im FK ab. | ||
| + | |||
| + | <WRAP tip round 80% center> | ||
| + | Merke: Fremdschlüssel geben Datensicherheit: | ||
| + | * Verhindern verwaiste Daten (z. B. Posts ohne gültigen Autor), | ||
| + | * definieren klares Verhalten bei Löschen/ | ||
| + | * halten die Datenbank konsistent. | ||
| + | </ | ||
| + | <wrap lo> Ausblick: In **LU08d** fügen wir FKs per **ALTER TABLE** nachträglich hinzu und testen die Referenzaktionen **RESTRICT**, | ||