Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
modul:m290_guko:learningunits:lu08:aufgaben:a_fk_in_lu05 [2025/10/19 23:38] – gkoch | modul:m290_guko:learningunits:lu08:aufgaben:a_fk_in_lu05 [2025/10/20 00:04] (aktuell) – gkoch | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
- | ====== | + | ====== |
**Ziel der Übung:** | **Ziel der Übung:** | ||
Zeile 12: | Zeile 12: | ||
- | ==== 1) Ausgangsbasis | + | ==== 1) Ausgangsbasis ==== |
* Öffnet eure **LU05-Datenbank** in WebStorm/ | * Öffnet eure **LU05-Datenbank** in WebStorm/ | ||
Zeile 32: | Zeile 32: | ||
**SQL-Muster (anpassen): | **SQL-Muster (anpassen): | ||
+ | <WRAP center box round 80%> | ||
<code sql> | <code sql> | ||
ALTER TABLE < | ALTER TABLE < | ||
Zeile 40: | Zeile 41: | ||
ON UPDATE RESTRICT; | ON UPDATE RESTRICT; | ||
</ | </ | ||
+ | </ | ||
- | < | + | < |
**Hinweise: | **Hinweise: | ||
- | * Die **Eltern-Tabelle** (referenzierte Tabelle) muss **vorher existieren**. | + | |
- | * Der **Datentyp** der FK-Spalte muss zum PK der Eltern passen (z. B. beide '' | + | * Der **Datentyp** der FK-Spalte muss zum PK der Eltern passen (z. B. beide '' |
- | * '' | + | * '' |
</ | </ | ||
- | ==== 4) DML testen – zeigt RESTRICT in Aktion ==== | ||
- | Führt die folgenden Mini-Tests in **eurem Case** durch. Erwartetes Verhalten jeweils in Klammern. | ||
- | **A. INSERT (gültige vs. ungültige FK-Werte)** <code sql> | + | ==== 3) DML testen – RESTRICT erfahrbar machen ==== |
- | -- gültig (Eltern existieren) | + | //DML = Data Manipulation Language |
- | INSERT INTO < | + | |
- | -- ungültig | + | **So gehen Sie vor (für euren gewählten Case):** |
- | INSERT INTO < | + | |
- | **B. DELETE Eltern (mit vorhandenen Kindern)** <code sql> | + | 1. **Daten anlegen** |
- | -- sollte scheitern | + | 2. **Tests A–D** ausführen und das Verhalten beobachten |
- | DELETE FROM < | + | |
- | WHERE < | + | |
- | **C. UPDATE FK in Kind (umhängen auf anderen Eltern-Datensatz)** <code sql> | + | > Hinweis: Falls eure Tabellennamen und Spaltennamen abweichen, dann müsst ihr das entsprechend ändern. Also entweder die hier erwähnten Codesnippets anpassen oder die Spaltennamen bei euch ändern. |
- | -- erlaubt, solange der neue Eltern-Datensatz existiert | + | |
- | UPDATE < | + | |
- | SET < | + | |
- | WHERE < | + | |
- | **D. UPDATE PK in Eltern | + | === Case: Tierheim |
- | -- in der Praxis selten und oft verhindert (RESTRICT). | + | |
- | -- Erwartung: scheitert, wenn Kindzeilen darauf verweisen. | + | |
- | UPDATE < | + | |
- | SET < | + | |
- | WHERE < | + | |
- | < | + | **FK:** // |
- | **Interpretation: | + | |
- | Ihr erlebt, dass die Datenbank | + | **Daten** |
- | Eltern | + | < |
- | Kind-Datensätze dürfen umgehängt werden | + | INSERT INTO tierart (art_id, bezeichnung) VALUES (1,' |
+ | INSERT INTO tier (tier_id, name, geburtsdatum, | ||
+ | VALUES (101,' | ||
+ | </ | ||
+ | |||
+ | **Tests A–D** | ||
+ | <WRAP center box 80% round>< | ||
+ | -- A) INSERT: gültig vs. ungültig | ||
+ | INSERT INTO tier (tier_id, name, geburtsdatum, | ||
+ | VALUES (102,' | ||
+ | INSERT INTO tier (tier_id, name, geburtsdatum, | ||
+ | VALUES (103,' | ||
+ | |||
+ | -- B) DELETE Eltern | ||
+ | DELETE FROM tierart WHERE art_id = 1; -- sollte scheitern (RESTRICT), weil Tier 101 darauf zeigt | ||
+ | |||
+ | -- C) UPDATE FK im Kind (umhängen) | ||
+ | UPDATE tier SET art_id = 2 WHERE tier_id = 101; -- ok (Katze existiert jetzt) | ||
+ | |||
+ | -- D) UPDATE PK in Eltern | ||
+ | UPDATE tierart SET art_id = 5 WHERE art_id = 2; -- sollte scheitern, solange Tiere auf 2 verweisen </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | === Case: Postzustellung (Postgebiet → viele Briefkästen) === | ||
+ | |||
+ | **FK:** // | ||
+ | |||
+ | **Daten** | ||
+ | <WRAP center box 80% round> | ||
+ | <code sql> | ||
+ | INSERT INTO postgebiet (gebiet_id, name, plz_bereich) VALUES (10,' | ||
+ | (20,' | ||
+ | INSERT INTO briefkasten (briefkasten_id, | ||
+ | VALUES (501,' | ||
+ | |||
+ | **Tests A–D** | ||
+ | <WRAP center box 80% round>< | ||
+ | -- A) INSERT | ||
+ | INSERT INTO briefkasten (briefkasten_id, | ||
+ | VALUES (502,' | ||
+ | INSERT INTO briefkasten (briefkasten_id, | ||
+ | VALUES (503,' | ||
+ | |||
+ | -- B) DELETE | ||
+ | DELETE FROM postgebiet WHERE gebiet_id = 10; -- scheitert (RESTRICT), weil BK 501 darauf zeigt | ||
+ | |||
+ | -- C) UPDATE FK im Kind | ||
+ | UPDATE briefkasten SET gebiet_id = 20 WHERE briefkasten_id = 501; -- ok (Gebiet 20 existiert) | ||
+ | |||
+ | -- D) UPDATE PK in Eltern | ||
+ | UPDATE postgebiet SET gebiet_id = 11 WHERE gebiet_id = 20; -- scheitert, solange Kinder | ||
+ | |||
+ | === Case: Online-Kleidershop (Kategorie → viele Kleidungsstücke) === | ||
+ | |||
+ | **FK:** // | ||
+ | |||
+ | **Daten** | ||
+ | <WRAP center box 80% round>< | ||
+ | INSERT INTO kategorie (kategorie_id, | ||
+ | INSERT INTO kleidungsstueck (artikel_id, | ||
+ | VALUES (9001,' | ||
+ | </ | ||
+ | |||
+ | **Tests A–D** | ||
+ | <WRAP center box 80% round>< | ||
+ | -- A) INSERT | ||
+ | INSERT INTO kleidungsstueck (artikel_id, | ||
+ | VALUES (9002,' | ||
+ | INSERT INTO kleidungsstueck (artikel_id, | ||
+ | VALUES (9003,' | ||
+ | |||
+ | -- B) DELETE Eltern | ||
+ | DELETE FROM kategorie WHERE kategorie_id = 1; -- scheitert (RESTRICT), Schuh 9001 existiert | ||
+ | |||
+ | -- C) UPDATE FK im Kind | ||
+ | UPDATE kleidungsstueck SET kategorie_id = 2 WHERE artikel_id = 9001; -- ok | ||
+ | |||
+ | -- D) UPDATE PK in Eltern | ||
+ | UPDATE kategorie SET kategorie_id = 5 WHERE kategorie_id = 2; -- scheitert bei referenzierten Zeilen </ | ||
+ | </ | ||
+ | |||
+ | === Case: Eishockeyverein (Team → viele Blöcke) === | ||
+ | |||
+ | **FK:** // | ||
+ | |||
+ | **Daten** | ||
+ | <WRAP center box 80% round>< | ||
+ | INSERT INTO team (team_id, name, altersklasse) VALUES (100,' | ||
+ | INSERT INTO block (block_id, bezeichnung, | ||
+ | </ | ||
+ | |||
+ | **Tests A–D** | ||
+ | <WRAP center box 80% round> | ||
+ | <code sql> | ||
+ | -- A) INSERT | ||
+ | INSERT INTO block (block_id, bezeichnung, | ||
+ | INSERT INTO block (block_id, bezeichnung, | ||
+ | |||
+ | -- B) DELETE Eltern | ||
+ | DELETE FROM team WHERE team_id = 100; -- scheitert (RESTRICT), Block 301 hängt dran | ||
+ | |||
+ | -- C) UPDATE FK im Kind | ||
+ | UPDATE block SET team_id = 200 WHERE block_id = 301; -- ok | ||
+ | |||
+ | -- D) UPDATE PK in Eltern | ||
+ | UPDATE team SET team_id = 250 WHERE team_id = 200; -- scheitert, wenn Blocks | ||
+ | </ | ||
+ | |||
+ | |||
+ | === Case: Öffentlicher Verkehr (Linie → viele Fahrten) === | ||
+ | |||
+ | **FK:** // | ||
+ | |||
+ | **Daten** | ||
+ | <WRAP center box 80% round> | ||
+ | <code sql> | ||
+ | INSERT INTO linie (linien_id, name, betreiber) VALUES (7,' | ||
+ | INSERT INTO fahrt (fahrt_id, datum, abfahrtszeit, | ||
+ | VALUES (7001,' | ||
+ | </ | ||
+ | |||
+ | **Tests A–D** | ||
+ | <WRAP center box 80% round> | ||
+ | <code sql> | ||
+ | -- A) INSERT | ||
+ | INSERT INTO fahrt (fahrt_id, datum, abfahrtszeit, | ||
+ | VALUES (7002,' | ||
+ | INSERT INTO fahrt (fahrt_id, datum, abfahrtszeit, | ||
+ | VALUES (7003,' | ||
+ | |||
+ | -- B) DELETE | ||
+ | DELETE FROM linie WHERE linien_id = 7; -- scheitert (RESTRICT) | ||
+ | |||
+ | -- C) UPDATE FK im Kind | ||
+ | UPDATE fahrt SET linien_id = 9 WHERE fahrt_id = 7001; -- ok | ||
+ | |||
+ | -- D) UPDATE PK in Eltern | ||
+ | UPDATE linie SET linien_id = 10 WHERE linien_id = 9; -- scheitert bei referenzierten Zeilen | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | === Case: Schweizer Regionen (Kanton → viele Gemeinden) === | ||
+ | |||
+ | **FK:** //gemeinde.kanton_id// → // | ||
+ | |||
+ | **Daten** | ||
+ | <WRAP center box 80% round> | ||
+ | <code sql> | ||
+ | INSERT INTO kanton (kanton_id, name, einwohnerzahl, | ||
+ | (2,' | ||
+ | INSERT INTO gemeinde (gemeinde_id, | ||
+ | VALUES (10001,' | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | **Tests A–D** | ||
+ | <WRAP center box 80% round>< | ||
+ | -- A) INSERT | ||
+ | INSERT INTO gemeinde (gemeinde_id, | ||
+ | VALUES (10002,' | ||
+ | INSERT INTO gemeinde (gemeinde_id, | ||
+ | VALUES (10003,' | ||
+ | |||
+ | -- B) DELETE Eltern | ||
+ | DELETE FROM kanton WHERE kanton_id = 1; -- scheitert (RESTRICT), Zürich hängt dran | ||
+ | |||
+ | -- C) UPDATE FK im Kind | ||
+ | UPDATE gemeinde SET kanton_id = 2 WHERE gemeinde_id = 10001; | ||
+ | |||
+ | -- D) UPDATE PK in Eltern | ||
+ | UPDATE kanton SET kanton_id = 3 WHERE kanton_id = 2; -- scheitert bei referenzierten Zeilen | ||
+ | </ | ||
</ | </ | ||
- | ==== 5) (Optional) SET NULL oder CASCADE bewusst einsetzen ==== | + | ==== 4) (Optional) SET NULL oder CASCADE bewusst einsetzen ==== |
Falls in **eurem Modell** eine Beziehung **optional** ist (FK darf NULL sein), könnt ihr '' | Falls in **eurem Modell** eine Beziehung **optional** ist (FK darf NULL sein), könnt ihr '' | ||
Zeile 96: | Zeile 256: | ||
</ | </ | ||
- | *Einsatzbeispiel: | + | //Einsatzbeispiel: |
**CASCADE** verwenden wir bevorzugt bei **Zwischentabellen** (N:M). | **CASCADE** verwenden wir bevorzugt bei **Zwischentabellen** (N:M). | ||
- | Falls euer Case eine N: | + | Falls euer Case eine N: |
Für reine 1: | Für reine 1: | ||
- | ==== 6) Abgabe (pro Gruppe) ==== | + | ==== 5) Abgabe (pro Gruppe) ==== |
- | **Kurz-Beschrieb (Word-Dokument/PDF, max. 1 Seite)** mit: | + | **Kurz-Beschrieb (Word-Dokument |
* ERD (Crow’s Foot) mit PK/FK markiert. | * ERD (Crow’s Foot) mit PK/FK markiert. | ||
* Liste eurer **ALTER TABLE**-Befehle (FK-Namen, ON DELETE/ | * Liste eurer **ALTER TABLE**-Befehle (FK-Namen, ON DELETE/ |