Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Nächste Überarbeitung
Vorhergehende Überarbeitung
modul:m290_guko:learningunits:lu08:aufgaben:a_fk_in_lu05 [2025/10/19 23:19] – angelegt gkochmodul:m290_guko:learningunits:lu08:aufgaben:a_fk_in_lu05 [2025/10/20 00:04] (aktuell) gkoch
Zeile 1: Zeile 1:
-====== LU08 – Praxisauftrag: Fremdschlüssel per ALTER TABLE + DML üben ======+====== LU08A1: Fremdschlüssel per ALTER TABLE + DML üben ======
  
 **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**, +  testet die **Referenzaktionen** (Standard: RESTRICT), 
-2. testet die **Referenzaktionen** (Standard: RESTRICT), +  übt **DML** (INSERT, UPDATE, DELETE) aus LU07.
-3. übt **DML** (INSERT, UPDATE, DELETE) aus LU07.+
  
 Arbeitsform: **2er-Gruppen** · Zeit: 1–2 Lektionen · Hilfsmittel: Kursunterlagen LU07/LU08 · Abgabe: siehe unten Arbeitsform: **2er-Gruppen** · Zeit: 1–2 Lektionen · Hilfsmittel: Kursunterlagen LU07/LU08 · Abgabe: siehe unten
  
---- 
  
-==== 1) Ausgangsbasis vorbereiten ====+==== 1) Ausgangsbasis ====
  
-* Öffnet eure **LU05-Datenbank** in WebStorm/MySQL. +  * Öffnet eure **LU05-Datenbank** in WebStorm/MySQL. 
-* 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 mit Beziehungen). +  * 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. ''tierheim_fk'') oder sichert euer altes mit ''CREATE DATABASE … LIKE …'' / ''mysqldump'', damit ihr gefahrlos testen könnt. +
-</WRAP>+
  
---- 
  
 ==== 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:N-Beziehung** den Fremdschlüssel fest: Analysiert euer ERD (Crow’s Foot aus LU05). Legt für **jede 1:N-Beziehung** den Fremdschlüssel fest:
  
-Beispiele (je nach Case anpassen):+Beispiele:
  
-* **Tierheim:** +  * **Tierheim:** //tier.art_id// → //tierart.art_id//, //tier.gehege_id// → //gehege.gehege_id// 
-  ''tier.art_id'' → ''tierart.art_id'' (N:1) +  * **Postzustellung:** //briefkasten.gebiet_id// → //postgebiet.gebiet_id//, //poestler.gebiet_id// → //postgebiet.gebiet_id// 
-  ''tier.gehege_id'' → ''gehege.gehege_id'' (N:1)+  * **Online-Kleidershop:** //kleidungsstueck.kategorie_id// → //kategorie.kategorie_id//, //kleidungsstueck.marke_id// → //marke.marke_id// 
 +  * **Eishockeyverein:** //block.team_id// → //team.team_id//, //spieler.block_id// → //block.block_id// 
 +  * **ÖV:** //haltestelle.linie_id// → //linie.linie_id//, //fahrt.linie_id// → //linie.linie_id// 
 +  * **Schweizer Regionen:** //gemeinde.kanton_code// → //kanton.kanton_code//, //gemeinde.kva_id// → //kva.anlage_id//
  
-* **Postzustellung:** +**SQL-Muster (anpassen):** 
-  ''briefkasten.gebiet_id'' → ''postgebiet.gebiet_id'' (N:1) +<WRAP center box round 80%> 
-  ''poestler.gebiet_id'' → ''postgebiet.gebiet_id'' (N:1) +<code sql>
- +
-* **Online-Kleidershop:** +
-  ''kleidungsstueck.kategorie_id'' → ''kategorie.kategorie_id'' (N:1) +
-  ''kleidungsstueck.marke_id'' → ''marke.marke_id'' (N:1) +
- +
-* **Eishockeyverein:** +
-  ''block.team_id'' → ''team.team_id'' (N:1) +
-  ''spieler.block_id'' → ''block.block_id'' (N:1) +
-  ''team.trainer_id'' → ''trainer.trainer_id'' (optional, wenn 1 Trainer mehrere Teams betreuen kann) +
- +
-* **ÖV (vereinfacht):** +
-  ''haltestelle.linie_id'' → ''linie.linie_id'' (N:1) +
-  ''fahrt.linie_id'' → ''linie.linie_id'' (N:1) +
- +
-* **Schweizer Regionen:** +
-  ''gemeinde.kanton_code'' → ''kanton.kanton_code'' (N:1) +
-  ''gemeinde.kva_id'' → ''kva.anlage_id'' (N:1) +
- +
-**SQL-Muster (anpassen):** <code sql>+
 ALTER TABLE <kind_tabelle> ALTER TABLE <kind_tabelle>
 ADD CONSTRAINT fk_<kind>_<eltern> ADD CONSTRAINT fk_<kind>_<eltern>
Zeile 62: Zeile 39:
 REFERENCES <eltern_tabelle>(<pk_spalte>) REFERENCES <eltern_tabelle>(<pk_spalte>)
 ON DELETE RESTRICT ON DELETE RESTRICT
-ON UPDATE RESTRICT; </code>+ON UPDATE RESTRICT; 
 +</code
 +</WRAP>
  
-<WRAP info>+<WRAP center box round 80%>
 **Hinweise:** **Hinweise:**
-* Die **Eltern-Tabelle** (referenzierte Tabelle) muss **vorher existieren**.   +  * Die **Eltern-Tabelle** (referenzierte Tabelle) muss **vorher existieren**.   
-* Der **Datentyp** der FK-Spalte muss zum PK der Eltern passen (z. B. beide ''INT'').   +  * Der **Datentyp** der FK-Spalte muss zum PK der Eltern passen (z. B. beide ''INT'').   
-* ''RESTRICT'' ist ein sicherer Standard: Löschen/Ändern der Elternzeile ist **verboten**, solange Kindzeilen darauf zeigen.+  * ''RESTRICT'' ist ein sicherer Standard: Löschen/Ändern der Elternzeile ist **verboten**, solange Kindzeilen darauf zeigen.
 </WRAP> </WRAP>
  
---- 
  
-==== 3) Konsistenz prüfen (Orphans suchen) ==== 
-Bevor ihr FKs setzt, **prüft** mit einer Links-Prüfung, ob es verwaiste Daten gibt: 
  
 +==== 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:** //tier.art_id// → //tierart.art_id//
 +
 +**Daten**
 +<WRAP center box 80% round><code sql>
 +INSERT INTO tierart (art_id, bezeichnung) VALUES (1,'Hund'), (2,'Katze');
 +INSERT INTO tier (tier_id, name, geburtsdatum, geschlecht, art_id)
 +VALUES (101,'Luna','2022-05-10','w',1); -- Kind zeigt auf Hund (1) </code>
 +</WRAP>
 +
 +**Tests A–D**
 +<WRAP center box 80% round><code sql>
 +-- A) INSERT: gültig vs. ungültig
 +INSERT INTO tier (tier_id, name, geburtsdatum, geschlecht, art_id)
 +VALUES (102,'Milo','2023-01-03','m',2); -- ok (Katze existiert)
 +INSERT INTO tier (tier_id, name, geburtsdatum, geschlecht, art_id)
 +VALUES (103,'Nala','2023-03-01','w',9999); -- sollte scheitern (FK!)
 +
 +-- 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 </code>
 +</WRAP>
 +
 +
 +=== Case: Postzustellung (Postgebiet → viele Briefkästen) ===
 +
 +**FK:** //briefkasten.gebiet_id// → //postgebiet.gebiet_id//
 +
 +**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,'Stadt Nord','8000-8099'), 
-SELECT k.* +(20,'Stadt Süd','8100-8199'); 
-FROM <kind_tabelle>+INSERT INTO briefkasten (briefkasten_id, standort, leerungszeit, gebiet_id) 
-LEFT JOIN <eltern_tabelle> e +VALUES (501,'Bahnhofplatz','18:00',10);  -- Kind zeigt auf Gebiet 10 </code></WRAP>
-  ON k.<fk_spalte= e.<pk_spalte> +
-WHERE e.<pk_spalte> IS NULL; +
-</code>+
  
-*Falls es Treffer gibt:Korrigiert die Werte (UPDATEoder löscht fehlerhafte Zeilen (DELETE), dann erst den FK setzen.+**Tests A–D** 
 +<WRAP center box 80% round><code sql> 
 +-- A) INSERT 
 +INSERT INTO briefkasten (briefkasten_id, standort, leerungszeit, gebiet_id) 
 +VALUES (502,'Zentrum','17:30',20); -- ok 
 +INSERT INTO briefkasten (briefkasten_idstandort, leerungszeit, gebiet_id) 
 +VALUES (503,'Park','17:00',9999); -- FK-Fehler erwartet
  
----+-- B) DELETE Eltern 
 +DELETE FROM postgebiet WHERE gebiet_id = 10; -- scheitert (RESTRICT), weil BK 501 darauf zeigt
  
-==== 4DML testen – zeigt RESTRICT in Aktion ==== +-- CUPDATE FK im Kind 
-Führt die folgenden Mini-Tests in **eurem Case** durch. Erwartetes Verhalten jeweils in Klammern.+UPDATE briefkasten SET gebiet_id 20 WHERE briefkasten_id 501;  -- ok (Gebiet 20 existiert)
  
-**A. INSERT (gültige vs. ungültige FK-Werte)** <code sql> +-- DUPDATE PK in Eltern 
--- gültig (Eltern existieren) +UPDATE postgebiet SET gebiet_id = 11 WHERE gebiet_id = 20; -- scheitertsolange Kinder auf 20 zeigen </code></WRAP>
-INSERT INTO <kind_tabelle>(..., <fk_spalte>) VALUES (..., <existierender_pk>);+
  
--- ungültig (Eltern existieren nicht) → sollte scheitern +=== Case: Online-Kleidershop (Kategorie → viele Kleidungsstücke===
-INSERT INTO <kind_tabelle>(..., <fk_spalte>) VALUES (..., 999999); </code>+
  
-**B. DELETE Eltern (mit vorhandenen Kindern)** <code sql> +**FK:** //kleidungsstueck.kategorie_id// → //kategorie.kategorie_id//
--- sollte scheitern (RESTRICT) +
-DELETE FROM <eltern_tabelle> +
-WHERE <pk_spalte> = <wert_mit_kindern>; </code>+
  
-**C. UPDATE FK in Kind (umhängen auf anderen Eltern-Datensatz)** <code sql> +**Daten** 
--- erlaubtsolange der neue Eltern-Datensatz existiert +<WRAP center box 80% round><code sql> 
-UPDATE <kind_tabelle> +INSERT INTO kategorie (kategorie_idname) VALUES (1,'Schuhe'), (2,'T-Shirts'); 
-SET <fk_spalte> = <anderer_existierender_pk+INSERT INTO kleidungsstueck (artikel_id, name, preis, groesse, zielgruppe, kategorie_id) 
-WHERE <kind_pk> = <id>; </code>+VALUES (9001,'City Sneaker',89.90,'42','Herren',1); </code
 +</WRAP>
  
-**D. UPDATE PK in Eltern (Primärschlüsselwert ändern)** <code sql> +**Tests A–D** 
--- in der Praxis selten und oft verhindert (RESTRICT). +<WRAP center box 80% round><code sql> 
--- Erwartung: scheitertwenn Kindzeilen darauf verweisen. +-- A) INSERT 
-UPDATE <eltern_tabelle> +INSERT INTO kleidungsstueck (artikel_id, name, preis, groesse, zielgruppe, kategorie_id
-SET <pk_spalte> = <neuer_pk> +VALUES (9002,'Basic Tee',19.90,'M','Damen',2);  -- ok 
-WHERE <pk_spalte> = <alter_pk></code>+INSERT INTO kleidungsstueck (artikel_idname, preis, groesse, zielgruppe, kategorie_id) 
 +VALUES (9003,'Ghost Item',9.90,'S','Damen',9999)-- FK-Fehler
  
-<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/umbenennensolange Kinder daran hängen.   +-- C) UPDATE FK im Kind 
-Kind-Datensätze dürfen umgehängt werden – aber nur auf **existierende** Eltern.+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 </code>
 </WRAP> </WRAP>
  
----+=== Case: Eishockeyverein (Team → viele Blöcke) ===
  
-==== 5) (Optional) SET NULL oder CASCADE bewusst einsetzen ==== +**FK:** //block.team_id// → //team.team_id//
-Falls in **eurem Modell** eine Beziehung **optional** ist (FK darf NULL sein), könnt ihr ''ON DELETE SET NULL'' wählen:+
  
 +**Daten**
 +<WRAP center box 80% round><code sql>
 +INSERT INTO team (team_id, name, altersklasse) VALUES (100,'U18','U18'), (200,'Herren','Aktiv');
 +INSERT INTO block (block_id, bezeichnung, team_id) VALUES (301,'Erste Linie',100); </code>
 +</WRAP>
 +
 +**Tests A–D**
 +<WRAP center box 80% round>
 <code sql> <code sql>
-ALTER TABLE <kind_tabelle> +-- A) INSERT 
-  ADD CONSTRAINT fk_<kind>_<eltern>  +INSERT INTO block (block_id, bezeichnung, team_id) VALUES (302,'Powerplay',200);  -- ok 
-    FOREIGN KEY (<fk_spalte>) +INSERT INTO block (block_id, bezeichnung, team_idVALUES (303,'Penaltykill',999); -- FK-Fehler
-    REFERENCES <eltern_tabelle>(<pk_spalte>) +
-    ON DELETE SET NULL +
-    ON UPDATE RESTRICT; +
-</code>+
  
-*Einsatzbeispiel:* ''team.trainer_id'' darf leer sein → beim Löschen eines Trainers bleibt das Team bestehen''trainer_id'' wird **NULL**.+-- 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). +-- CUPDATE FK im Kind 
-Falls euer Case eine N:M-Erweiterung hat (z. B. im Kleidershop: *Artikel ↔ Größe*), legt ihr die Junction-Tabelle in **LU08e** an und setzt dort **CASCADE**. +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 </code> 
 +</WRAP>
  
-==== 6) Abgabe (pro Gruppe) ==== 
  
-1. **Kurz-Doku (max. 1 Seite)** mit:+=== Case: Öffentlicher Verkehr (Linie → viele Fahrten===
  
-   * ERD (Crow’s Foot) mit PK/FK markiert. +**FK:** //fahrt.linien_id// → //linie.linien_id//
-   * Liste eurer **ALTER TABLE**-Befehle (FK-Namen, ON DELETE/UPDATE-Regeln). +
-   3–5 **DML-Beispiele** (INSERT/UPDATE/DELETE) inklkurzer 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.+
  
-<WRAP info+**Daten** 
-**Bewertung (Kurzrubrik):**   +<WRAP center box 80% round
-Vollständigkeit FK (40 %), saubere DML-Tests & Interpretation (40 %)Benennung/Lesbarkeit (20 %).+<code sql> 
 +INSERT INTO linie (linien_id, name, betreiberVALUES (7,'Tram 7','VBZ'), (9,'Bus 9','VBZ'); 
 +INSERT INTO fahrt (fahrt_id, datum, abfahrtszeit, preis, linien_id) 
 +VALUES (7001,'2025-11-05','07:45',3.80,7);</code>
 </WRAP> </WRAP>
  
----+**Tests A–D** 
 +<WRAP center box 80% round> 
 +<code sql> 
 +-- A) INSERT 
 +INSERT INTO fahrt (fahrt_id, datum, abfahrtszeit, preis, linien_id) 
 +VALUES (7002,'2025-11-05','08:15',3.80,9);  -- ok 
 +INSERT INTO fahrt (fahrt_id, datum, abfahrtszeit, preis, linien_id) 
 +VALUES (7003,'2025-11-05','09:00',3.80,99);  -- FK-Fehler
  
-==== Anhang: Vorlagen je Case (FK-Skizzen) ==== +-- BDELETE Eltern 
-*Tierheim* <code sql> +DELETE FROM linie WHERE linien_id 7; -- scheitert (RESTRICT)
-ALTER TABLE tier +
-ADD CONSTRAINT fk_tier_art +
-FOREIGN KEY (art_id) REFERENCES tierart(art_id) ON DELETE RESTRICT ON UPDATE RESTRICT, +
-ADD CONSTRAINT fk_tier_gehege +
-FOREIGN KEY (gehege_idREFERENCES gehege(gehege_id) ON DELETE RESTRICT ON UPDATE RESTRICT; </code>+
  
-*Postzustellung* <code sql> +-- C) UPDATE FK im Kind 
-ALTER TABLE briefkasten +UPDATE fahrt SET linien_id = 9 WHERE fahrt_id = 7001-- ok
-ADD CONSTRAINT fk_briefkasten_gebiet +
-FOREIGN KEY (gebiet_id) REFERENCES postgebiet(gebiet_id) ON DELETE RESTRICT ON UPDATE RESTRICT;+
  
-ALTER TABLE poestler +-- D) UPDATE PK in Eltern 
-ADD CONSTRAINT fk_poestler_gebiet +UPDATE linie SET linien_id = 10 WHERE linien_id = 9-- scheitert bei referenzierten Zeilen 
-FOREIGN KEY (gebiet_idREFERENCES postgebiet(gebiet_id) ON DELETE RESTRICT ON UPDATE RESTRICT; </code>+</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; </code> 
  
-*Eishockeyverein* <code sql> +=== Case: Schweizer Regionen (Kanton → viele Gemeinden===
-ALTER TABLE block +
-ADD CONSTRAINT fk_block_team +
-FOREIGN KEY (team_idREFERENCES team(team_id) ON DELETE RESTRICT ON UPDATE RESTRICT;+
  
-ALTER TABLE spieler +**FK:** //gemeinde.kanton_id// → //kanton.kanton_id//
-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_idREFERENCES trainer(trainer_idON DELETE SET NULL ON UPDATE RESTRICT-- optional </code>+<code sql> 
 +INSERT INTO kanton (kanton_id, name, einwohnerzahl, flaecheVALUES (1,'ZH',1550000,1729), 
 +(2,'GR',200000,7105); 
 +INSERT INTO gemeinde (gemeinde_id, name, plz, kanton_id) 
 +VALUES (10001,'Zürich','8001',1); 
 +</code
 +</WRAP>
  
-*Öffentlicher Verkehr (vereinfacht)* <code sql> +**Tests A–D** 
-ALTER TABLE haltestelle +<WRAP center box 80% round><code sql> 
-ADD CONSTRAINT fk_haltestelle_linie +-- A) INSERT 
-FOREIGN KEY (linie_id) REFERENCES linie(linie_id) ON DELETE RESTRICT ON UPDATE RESTRICT;+INSERT INTO gemeinde (gemeinde_id, name, plz, kanton_id) 
 +VALUES (10002,'Chur','7000',2); -- ok 
 +INSERT INTO gemeinde (gemeinde_id, name, plz, kanton_id) 
 +VALUES (10003,'Nowhere','9999',999); -- FK-Fehler 
 + 
 +-- 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;  -- ok 
 + 
 +-- D) UPDATE PK in Eltern 
 +UPDATE kanton SET kanton_id = 3 WHERE kanton_id = 2; -- scheitert bei referenzierten Zeilen 
 +</code> 
 +</WRAP> 
 + 
 +==== 4) (Optional) SET NULL oder CASCADE bewusst einsetzen ==== 
 +Falls in **eurem Modell** eine Beziehung **optional** ist (FK darf NULL sein), könnt ihr ''ON DELETE SET NULL'' wählen: 
 + 
 +<code sql> 
 +ALTER TABLE <kind_tabelle> 
 +  ADD CONSTRAINT fk_<kind>_<eltern>  
 +    FOREIGN KEY (<fk_spalte>) 
 +    REFERENCES <eltern_tabelle>(<pk_spalte>) 
 +    ON DELETE SET NULL 
 +    ON UPDATE RESTRICT; 
 +</code> 
 + 
 +//Einsatzbeispiel:// ''team.trainer_id'' darf leer sein → beim Löschen eines Trainers bleibt das Team bestehen, ''trainer_id'' wird **NULL**. 
 + 
 +**CASCADE** verwenden wir bevorzugt bei **Zwischentabellen** (N:M). 
 +Falls euer Case eine N:M-Erweiterung hat (z. B. im Kleidershop: //Artikel ↔ Grösse//), legt ihr die Zwischen-Tabelle wie in **LU08e** an und setzt dort **CASCADE**. 
 +Für reine 1:N-Beziehungen bleibt **RESTRICT** meist die beste Wahl. 
 + 
 +==== 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/UPDATE-Regeln). 
 +   * 3–5 **DML-Beispiele** (INSERT/UPDATE/DELETE) inkl. kurzer Interpretation des Verhaltens (z. B. Fehlermeldung bei RESTRICT).
  
-ALTER TABLE fahrt 
-ADD CONSTRAINT fk_fahrt_linie 
-FOREIGN KEY (linie_id) REFERENCES linie(linie_id) ON DELETE RESTRICT ON UPDATE RESTRICT; </code> 
  
-*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; </code> 
  
  • modul/m290_guko/learningunits/lu08/aufgaben/a_fk_in_lu05.1760908791.txt.gz
  • Zuletzt geändert: 2025/10/19 23:19
  • von gkoch