Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
modul:m290_guko:learningunits:lu08:aufgaben:a_fk_in_lu05 [2025/10/19 23:19] – angelegt 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:** | ||
- | Ihr greift euren **LU05-Case** wieder auf (z. B. *Tierheim*, *Postzustellung*, *Online-Kleidershop*, *Eishockeyverein*, *ÖV*, *Schweizer Regionen*). | + | Ihr greift euren **LU05-Case** wieder auf (z. B. //Tierheim//, //Postzustellung//, //Online-Kleidershop//, //Eishockeyverein//, //ÖV//, //Schweizer Regionen//). |
Damals habt ihr Tabellen **ohne** Fremdschlüssel erstellt und Daten via WebStorm-Interface eingefügt. | Damals habt ihr Tabellen **ohne** Fremdschlüssel erstellt und Daten via WebStorm-Interface eingefügt. | ||
Jetzt | Jetzt | ||
- | + | - ergänzt ihr **Fremdschlüssel mit ALTER TABLE**, | |
- | 1. ergänzt ihr **Fremdschlüssel mit ALTER TABLE**, | + | |
- | 2. testet die **Referenzaktionen** (Standard: RESTRICT), | + | |
- | 3. übt **DML** (INSERT, UPDATE, DELETE) aus LU07. | + | |
Arbeitsform: | Arbeitsform: | ||
- | --- | ||
- | ==== 1) Ausgangsbasis | + | ==== 1) Ausgangsbasis ==== |
- | * Öffnet eure **LU05-Datenbank** in WebStorm/ | + | |
- | * Prüft, dass **Primärschlüssel vorhanden** sind (wie in LU05), aber **keine** Fremdschlüssel. | + | * Prüft, dass **Primärschlüssel vorhanden** sind (wie in LU05), aber **keine** Fremdschlüssel. |
- | * Falls ihr neu starten wollt: erstellt die Tabellen nochmals wie in LU05 (PK ja, FK noch nicht) und füllt ein paar **Beispieldaten** ein (mind. 3–5 Zeilen pro Tabelle | + | * Falls ihr neu starten wollt: erstellt die Tabellen nochmals wie in LU05 (PK ja, FK noch nicht) und füllt ein paar **Beispieldaten** ein (mind. 3 Zeilen pro Tabelle). |
- | + | ||
- | <WRAP tip> | + | |
- | **Tipp:** Arbeitet in einem **neuen Schema** (z. B. '' | + | |
- | </ | + | |
- | --- | ||
==== 2) Fremdschlüssel mit ALTER TABLE hinzufügen ==== | ==== 2) Fremdschlüssel mit ALTER TABLE hinzufügen ==== | ||
Analysiert euer ERD (Crow’s Foot aus LU05). Legt für **jede 1: | Analysiert euer ERD (Crow’s Foot aus LU05). Legt für **jede 1: | ||
- | Beispiele | + | Beispiele: |
- | * **Tierheim: | + | |
- | '' | + | * **Postzustellung:** // |
- | '' | + | * **Online-Kleidershop: |
+ | * **Eishockeyverein: | ||
+ | * **ÖV:** // | ||
+ | * **Schweizer Regionen:** // | ||
- | * **Postzustellung: | + | **SQL-Muster (anpassen): |
- | '' | + | <WRAP center box round 80%> |
- | '' | + | <code sql> |
- | + | ||
- | * **Online-Kleidershop: | + | |
- | '' | + | |
- | '' | + | |
- | + | ||
- | * **Eishockeyverein: | + | |
- | '' | + | |
- | '' | + | |
- | '' | + | |
- | + | ||
- | * **ÖV (vereinfacht): | + | |
- | '' | + | |
- | '' | + | |
- | + | ||
- | * **Schweizer Regionen: | + | |
- | '' | + | |
- | '' | + | |
- | + | ||
- | **SQL-Muster (anpassen): | + | |
ALTER TABLE < | ALTER TABLE < | ||
ADD CONSTRAINT fk_< | ADD CONSTRAINT fk_< | ||
Zeile 62: | Zeile 39: | ||
REFERENCES < | REFERENCES < | ||
ON DELETE RESTRICT | ON DELETE RESTRICT | ||
- | ON UPDATE RESTRICT; </ | + | ON UPDATE RESTRICT; |
+ | </code> | ||
+ | </WRAP> | ||
- | < | + | < |
**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 '' |
- | * '' | + | * '' |
</ | </ | ||
- | --- | ||
- | ==== 3) Konsistenz prüfen (Orphans suchen) ==== | ||
- | Bevor ihr FKs setzt, **prüft** mit einer Links-Prüfung, | ||
+ | ==== 3) DML testen – RESTRICT erfahrbar machen ==== | ||
+ | //DML = Data Manipulation Language -> Daten einfügen, ändern, löschen// | ||
+ | |||
+ | **So gehen Sie vor (für euren gewählten Case):** | ||
+ | |||
+ | 1. **Daten anlegen** | ||
+ | 2. **Tests A–D** ausführen und das Verhalten beobachten (Kommentar sagt, was passieren soll). | ||
+ | |||
+ | > 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. | ||
+ | |||
+ | === Case: Tierheim (Tierart → viele Tiere) == | ||
+ | |||
+ | **FK:** // | ||
+ | |||
+ | **Daten** | ||
+ | <WRAP center box 80% round>< | ||
+ | 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 mit Kind | ||
+ | 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> | <code sql> | ||
- | -- Beispiel: Kinder ohne Eltern finden | + | INSERT INTO postgebiet (gebiet_id, name, plz_bereich) VALUES (10,' |
- | SELECT k.* | + | (20,' |
- | FROM < | + | INSERT INTO briefkasten (briefkasten_id, |
- | LEFT JOIN < | + | VALUES (501,' |
- | | + | |
- | WHERE e.< | + | |
- | </code> | + | |
- | *Falls es Treffer gibt:* Korrigiert die Werte (UPDATE) oder löscht fehlerhafte Zeilen | + | **Tests A–D** |
+ | <WRAP center box 80% round>< | ||
+ | -- A) INSERT | ||
+ | INSERT INTO briefkasten | ||
+ | VALUES | ||
+ | INSERT INTO briefkasten (briefkasten_id, standort, leerungszeit, | ||
+ | VALUES (503,' | ||
- | --- | + | -- B) DELETE Eltern |
+ | DELETE FROM postgebiet WHERE gebiet_id = 10; -- scheitert (RESTRICT), weil BK 501 darauf zeigt | ||
- | ==== 4) DML testen – zeigt RESTRICT in Aktion | + | -- C) UPDATE FK im Kind |
- | Führt die folgenden Mini-Tests in **eurem Case** durch. Erwartetes Verhalten jeweils in Klammern. | + | UPDATE briefkasten SET gebiet_id |
- | **A. INSERT (gültige vs. ungültige FK-Werte)** <code sql> | + | -- D) UPDATE PK in Eltern |
- | -- gültig (Eltern existieren) | + | UPDATE postgebiet SET gebiet_id = 11 WHERE gebiet_id = 20; -- scheitert, solange Kinder auf 20 zeigen |
- | INSERT INTO < | + | |
- | -- ungültig | + | === Case: Online-Kleidershop |
- | INSERT INTO < | + | |
- | **B. DELETE Eltern (mit vorhandenen Kindern)** <code sql> | + | **FK:** // |
- | -- sollte scheitern (RESTRICT) | + | |
- | DELETE FROM < | + | |
- | WHERE < | + | |
- | **C. UPDATE FK in Kind (umhängen auf anderen Eltern-Datensatz)** <code sql> | + | **Daten** |
- | -- erlaubt, solange der neue Eltern-Datensatz existiert | + | <WRAP center box 80% round><code sql> |
- | UPDATE < | + | INSERT INTO kategorie (kategorie_id, name) VALUES (1,' |
- | SET <fk_spalte> | + | INSERT INTO kleidungsstueck (artikel_id, |
- | WHERE < | + | VALUES (9001,' |
+ | </WRAP> | ||
- | **D. UPDATE PK in Eltern (Primärschlüsselwert ändern)** <code sql> | + | **Tests A–D** |
- | -- in der Praxis selten und oft verhindert | + | <WRAP center box 80% round><code sql> |
- | -- Erwartung: scheitert, wenn Kindzeilen darauf verweisen. | + | -- A) INSERT |
- | UPDATE < | + | INSERT INTO kleidungsstueck |
- | SET < | + | VALUES (9002,' |
- | WHERE < | + | INSERT INTO kleidungsstueck (artikel_id, name, preis, groesse, zielgruppe, kategorie_id) |
+ | VALUES (9003,' | ||
- | <WRAP tip> | + | -- B) DELETE Eltern |
- | **Interpretation: | + | DELETE FROM kategorie WHERE kategorie_id = 1; -- scheitert (RESTRICT), Schuh 9001 existiert |
- | Ihr erlebt, dass die Datenbank mit **RESTRICT** die **Datenintegrität** schützt: | + | |
- | Eltern lassen sich nicht löschen/ | + | -- C) UPDATE FK im Kind |
- | Kind-Datensätze dürfen umgehängt werden – aber nur auf **existierende** | + | 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) === |
- | ==== 5) (Optional) SET NULL oder CASCADE bewusst einsetzen ==== | + | **FK:** // |
- | Falls in **eurem Modell** eine Beziehung **optional** ist (FK darf NULL sein), könnt ihr '' | + | |
+ | **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> | <code sql> | ||
- | ALTER TABLE < | + | -- A) INSERT |
- | | + | INSERT INTO block (block_id, bezeichnung, |
- | | + | INSERT INTO block (block_id, bezeichnung, |
- | REFERENCES < | + | |
- | ON DELETE SET NULL | + | |
- | ON UPDATE RESTRICT; | + | |
- | </ | + | |
- | *Einsatzbeispiel: | + | -- B) DELETE Eltern |
+ | DELETE FROM team WHERE team_id = 100; -- scheitert (RESTRICT), Block 301 hängt dran | ||
- | **CASCADE** verwenden wir bevorzugt bei **Zwischentabellen** (N:M). | + | -- C) UPDATE FK im Kind |
- | Falls euer Case eine N:M-Erweiterung hat (z. B. im Kleidershop: | + | UPDATE block SET team_id = 200 WHERE block_id = 301; -- ok |
- | Für reine 1:N-Beziehungen bleibt **RESTRICT** meist die beste Wahl. | + | |
- | --- | + | -- D) UPDATE PK in Eltern |
+ | UPDATE team SET team_id = 250 WHERE team_id = 200; -- scheitert, wenn Blocks auf 200 zeigen </ | ||
+ | </ | ||
- | ==== 6) Abgabe (pro Gruppe) ==== | ||
- | 1. **Kurz-Doku | + | === Case: Öffentlicher Verkehr |
- | * ERD (Crow’s Foot) mit PK/FK markiert. | + | **FK:** //fahrt.linien_id// → //linie.linien_id// |
- | * Liste eurer **ALTER TABLE**-Befehle (FK-Namen, ON DELETE/ | + | |
- | * 3–5 **DML-Beispiele** (INSERT/UPDATE/DELETE) inkl. kurzer Interpretation des Verhaltens (z. B. Fehlermeldung bei RESTRICT). | + | |
- | 2. **SQL-Datei** mit allen ausgeführten **ALTER/INSERT/UPDATE/DELETE** (in sinnvoller Reihenfolge). | + | |
- | 3. **Kurz-Demo** (2–3 Minuten): Ein FK-Fehler **zeigen** und erklären, warum er sinnvoll ist. | + | |
- | < | + | **Daten** |
- | **Bewertung | + | < |
- | Vollständigkeit FK (40 %), saubere DML-Tests & Interpretation | + | <code sql> |
+ | INSERT INTO linie (linien_id, name, betreiber) VALUES | ||
+ | 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,' | ||
- | ==== Anhang: Vorlagen je Case (FK-Skizzen) ==== | + | -- B) DELETE Eltern |
- | *Tierheim* <code sql> | + | DELETE FROM linie WHERE linien_id |
- | ALTER TABLE tier | + | |
- | ADD CONSTRAINT fk_tier_art | + | |
- | FOREIGN KEY (art_id) REFERENCES tierart(art_id) ON DELETE | + | |
- | ADD CONSTRAINT fk_tier_gehege | + | |
- | FOREIGN KEY (gehege_id) REFERENCES gehege(gehege_id) ON DELETE RESTRICT ON UPDATE RESTRICT; </ | + | |
- | *Postzustellung* <code sql> | + | -- C) UPDATE FK im Kind |
- | ALTER TABLE briefkasten | + | UPDATE |
- | ADD CONSTRAINT fk_briefkasten_gebiet | + | |
- | FOREIGN KEY (gebiet_id) REFERENCES postgebiet(gebiet_id) ON DELETE RESTRICT ON UPDATE | + | |
- | ALTER TABLE poestler | + | -- D) UPDATE |
- | ADD CONSTRAINT fk_poestler_gebiet | + | UPDATE linie SET linien_id = 10 WHERE linien_id = 9; -- scheitert bei referenzierten Zeilen |
- | FOREIGN KEY (gebiet_id) REFERENCES postgebiet(gebiet_id) ON DELETE RESTRICT ON UPDATE | + | </code> |
+ | </WRAP> | ||
- | *Online-Kleidershop* <code sql> | ||
- | ALTER TABLE kleidungsstueck | ||
- | ADD CONSTRAINT fk_kleid_kategorie | ||
- | FOREIGN KEY (kategorie_id) REFERENCES kategorie(kategorie_id) ON DELETE RESTRICT ON UPDATE RESTRICT, | ||
- | ADD CONSTRAINT fk_kleid_marke | ||
- | FOREIGN KEY (marke_id) REFERENCES marke(marke_id) ON DELETE RESTRICT ON UPDATE RESTRICT; </ | ||
- | *Eishockeyverein* <code sql> | + | === Case: Schweizer Regionen |
- | ALTER TABLE block | + | |
- | ADD CONSTRAINT fk_block_team | + | |
- | FOREIGN KEY (team_id) REFERENCES team(team_id) ON DELETE RESTRICT ON UPDATE RESTRICT; | + | |
- | ALTER TABLE spieler | + | **FK:** // |
- | ADD CONSTRAINT fk_spieler_block | + | |
- | FOREIGN KEY (block_id) REFERENCES block(block_id) ON DELETE RESTRICT ON UPDATE RESTRICT; | + | |
- | ALTER TABLE team | + | **Daten** |
- | ADD CONSTRAINT fk_team_trainer | + | <WRAP center box 80% round> |
- | FOREIGN KEY (trainer_id) REFERENCES trainer(trainer_id) ON DELETE SET NULL ON UPDATE RESTRICT; -- optional | + | <code sql> |
+ | INSERT INTO kanton | ||
+ | (2,' | ||
+ | INSERT INTO gemeinde (gemeinde_id, | ||
+ | VALUES (10001,' | ||
+ | </code> | ||
+ | </WRAP> | ||
- | *Öffentlicher Verkehr | + | **Tests A–D** |
- | ALTER TABLE haltestelle | + | <WRAP center box 80% round>< |
- | ADD CONSTRAINT | + | -- A) INSERT |
- | FOREIGN KEY (linie_id) REFERENCES | + | INSERT INTO gemeinde |
+ | 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 | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | ==== 4) (Optional) SET NULL oder CASCADE bewusst einsetzen ==== | ||
+ | Falls in **eurem Modell** eine Beziehung **optional** ist (FK darf NULL sein), könnt ihr '' | ||
+ | |||
+ | <code sql> | ||
+ | ALTER TABLE < | ||
+ | ADD CONSTRAINT | ||
+ | FOREIGN KEY (< | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | // | ||
+ | |||
+ | **CASCADE** verwenden wir bevorzugt bei **Zwischentabellen** (N:M). | ||
+ | Falls euer Case eine N: | ||
+ | Für reine 1: | ||
+ | |||
+ | ==== 5) Abgabe (pro Gruppe) ==== | ||
+ | |||
+ | **Kurz-Beschrieb (Word-Dokument oder PDF, max. 1 Seite)** mit: | ||
+ | * ERD (Crow’s Foot) mit PK/FK markiert. | ||
+ | * Liste eurer **ALTER TABLE**-Befehle (FK-Namen, ON DELETE/ | ||
+ | * 3–5 **DML-Beispiele** (INSERT/ | ||
- | ALTER TABLE fahrt | ||
- | ADD CONSTRAINT fk_fahrt_linie | ||
- | FOREIGN KEY (linie_id) REFERENCES linie(linie_id) ON DELETE RESTRICT ON UPDATE RESTRICT; </ | ||
- | *Schweizer Regionen* <code sql> | ||
- | ALTER TABLE gemeinde | ||
- | ADD CONSTRAINT fk_gemeinde_kanton | ||
- | FOREIGN KEY (kanton_code) REFERENCES kanton(kanton_code) ON DELETE RESTRICT ON UPDATE RESTRICT, | ||
- | ADD CONSTRAINT fk_gemeinde_kva | ||
- | FOREIGN KEY (kva_id) REFERENCES kva(anlage_id) ON DELETE RESTRICT ON UPDATE RESTRICT; </ | ||