sql/01_Datenbanken.sql (MySQL/SQLite).
Die Beispiele in diesem Teil verwenden bewusst andere Szenarien (Musikschule, Fitnessstudio) als die Aufgaben in Teil C (Fahrradverleih VeloPunkt). So lernst du die Methode, ohne die Lösung schon zu kennen.
Vorkommen: 9/9 · Prüfungen: alle (W21–S26) · meist Teil 2, Aufgabe 3 (16–25 P), zusätzlich in Teil 1 (W21, S23, W23, S24, W25)
Eine Datenbank wird in zwei Stufen entworfen:
CREATE TABLE-Befehle umsetzen.In der Prüfung wird meist das Relationenmodell in 3. Normalform verlangt („Erstellen Sie ein relationales Datenmodell in 3NF …“), seltener ein ER-Modell (W21 T1, W23 T1, S24 T1).
| Begriff | Bedeutung | Beispiel (Musikschule) |
|---|---|---|
| Entität | einzelnes, eindeutig unterscheidbares Objekt | die Schülerin Mia Kramer |
| Entitätstyp | Zusammenfassung gleichartiger Entitäten → wird zur Tabelle | Schüler |
| Attribut | Eigenschaft eines Entitätstyps → wird zur Spalte | Geburtsdatum |
| Schlüsselattribut | identifiziert jede Entität eindeutig (im ERM unterstrichen) → wird zum Primärschlüssel | SchülerNr |
| Beziehung(styp) | Zusammenhang zwischen Entitätstypen, mit einem Verb benannt | Schüler belegt Kurs |
| Kardinalität | wie viele Entitäten der einen Seite mit einer Entität der anderen Seite in Beziehung stehen können | 1:1, 1:n, m:n |
| Beziehungsattribut | Eigenschaft, die erst durch die Beziehung entsteht und zu keiner Entität allein gehört | Anmeldedatum (eines Schülers zu einem Kurs) |
Der Belegsatz zeigt nur die drei Symbole: Rechteck = Entität, Raute = Beziehung, Ellipse = Attribut. Die Kardinalitäten stehen nicht im Belegsatz – die musst du kennen. Man schreibt sie als 1, n oder m an die Verbindungslinien.
So liest du eine Beziehung: Von einer Entität über die Raute zur Zahl auf der anderen Seite: „Eine Abteilung beschäftigt n Mitarbeiter“ und „Ein Mitarbeiter wird von 1 Abteilung beschäftigt.“ Die Zahl steht also an der Entität, deren Anzahl sie angibt.
| Kardinalität | Bedeutung | Bestimmung durch zwei Fragen |
|---|---|---|
| 1:1 | Zu jedem A gehört höchstens ein B und umgekehrt. | Wie viele Ausweise hat eine Person? Einen. Wie vielen Personen gehört ein Ausweis? Einer. |
| 1:n | Ein A hat mehrere B, jedes B gehört zu genau einem A. | Wie viele Mitarbeiter hat eine Abteilung? Mehrere. In wie vielen Abteilungen arbeitet ein Mitarbeiter? In einer. |
| m:n | Ein A hat mehrere B und ein B hat mehrere A. | Wie viele Vorlesungen besucht ein Student? Mehrere. Wie viele Studenten besuchen eine Vorlesung? Mehrere. |
Ergänzung: Manche Lehrbücher nutzen die modifizierte Chen-Notation mit c (0 oder 1) und mc (0 bis viele) oder die Min-Max-Notation (0,1), (1,*). In den IHK-Lösungen genügen 1, n, m.
geloescht (boolean) oder GeloeschtAm (Datum). So bleiben Historie und Bezüge erhalten.Beispiel Musikschule: Eine Lehrkraft leitet mehrere Kurse, jeder Kurs hat genau eine Lehrkraft. Schüler belegen beliebig viele Kurse, ein Kurs hat viele Schüler; gespeichert wird das Anmeldedatum. Erfahrene Lehrkräfte betreuen als Mentor mehrere neue Lehrkräfte, jede Lehrkraft hat höchstens einen Mentor. Ein Schüler kann höchstens ein Leihinstrument ausleihen, ein Leihinstrument ist höchstens an einen Schüler verliehen.
| Begriff im Relationenmodell | Bedeutung |
|---|---|
| Relation / Tabelle | entspricht einem Entitätstyp (oder einer aufgelösten m:n-Beziehung) |
| Tupel / Datensatz / Zeile | eine Entität |
| Primärschlüssel (PK) | Spalte(n), die jede Zeile eindeutig identifizieren; nie NULL, nie doppelt |
| Zusammengesetzter Schlüssel | PK aus mehreren Spalten, typisch in Zwischentabellen |
| Surrogatschlüssel | künstliche, fortlaufende Nummer (ID) ohne fachliche Bedeutung |
| Fremdschlüssel (FK) | Spalte, die auf den PK einer anderen (oder derselben) Tabelle verweist und so die Beziehung herstellt |
Zwei übliche Darstellungen (beide werden in der Prüfung akzeptiert):
# oder „(FK)“) gekennzeichnet.1 und n an den Enden.| Im ER-Modell | Umsetzung im Relationenmodell |
|---|---|
| Entitätstyp | eigene Tabelle; das Schlüsselattribut wird PK |
| Attribut | Spalte; zusammengesetzte Attribute zerlegen (Anschrift → Straße, Hausnummer, PLZ, Ort; Name → Vorname, Nachname) |
| 1:n | PK der 1-Seite wird als FK in die Tabelle der n-Seite aufgenommen |
| 1:1 | FK in eine der beiden Tabellen – am besten in die Tabelle, deren Datensätze immer einen Partner haben (dann ist der FK nie NULL) – und zusätzlich UNIQUE, damit jeder Wert nur einmal vorkommt; alternativ beide Tabellen zusammenlegen |
| m:n | eigene Zwischentabelle (Verbindungstabelle) mit den PKs beider Seiten als FKs; beide zusammen bilden den PK. Beziehungsattribute kommen in die Zwischentabelle. Aus einer m:n werden zwei 1:n-Beziehungen. |
| rekursiv 1:n | FK in derselben Tabelle, der auf den eigenen PK zeigt (MentorNr → LehrerNr) |
| rekursiv m:n | Zwischentabelle mit zwei FKs auf dieselbe Tabelle, z. B. Stückliste(↑OberteilNr, ↑UnterteilNr, Menge) |
| mehrere Beziehungen zwischen denselben Tabellen | je Beziehung ein eigener FK mit sprechendem Namen, z. B. Spiel(SpielNr, ↑HeimTeamNr, ↑GastTeamNr) |
Dasselbe Modell in Textnotation:
Lehrkraft(LehrerNr, Name, Telefon, ↑MentorNr)
Kurs(KursNr, Titel, Wochentag, ↑LehrerNr)
Schueler(SchuelerNr, Vorname, Nachname, Geburtsdatum)
Belegung(↑SchuelerNr, ↑KursNr, Anmeldedatum)
Leihinstrument(InstrumentNr, Bezeichnung, ↑SchuelerNr) – SchuelerNr ist UNIQUE (1:1)
Vorkommen: 8/9 · Prüfungen: alle außer S24 · Teil 2, Aufgabe 3 und Teil 1 (S23, W25)
Redundanz = dieselbe Information ist mehrfach gespeichert. Das kostet Speicher, vor allem aber führt es zu Inkonsistenzen (widersprüchlichen Daten), weil Änderungen nicht überall nachgezogen werden. Ziel der Normalisierung: jede Information genau einmal speichern und so Anomalien verhindern.
Beispiel – unnormalisierte Kursliste einer Musikschule (Excel):
| KursNr | Kurstitel | LehrerNr | Lehrer | Raum | Teilnehmer |
|---|---|---|---|---|---|
| K1 | Gitarre Anfänger | L7 | Petra Lang | R2 | 101 Mia Kramer, 102 Noah Ernst |
| K2 | Klavier | L3 | Uwe Brandl | R1 | 101 Mia Kramer |
| K3 | Gitarre Fortgeschr. | L7 | Petra Lang | R2 | 103 Lea Fink, 102 Noah Ernst |
| Anomalie | Bedeutung | Beispiel aus der Kursliste |
|---|---|---|
| Einfügeanomalie | Ein Sachverhalt kann nicht gespeichert werden, ohne dass gleichzeitig ein anderer, noch nicht vorhandener Sachverhalt erfasst wird. | Eine neue Lehrkraft kann erst gespeichert werden, wenn sie einen Kurs hat (die Zeile braucht eine KursNr). |
| Änderungsanomalie | Eine Änderung muss an mehreren Stellen erfolgen; wird eine Stelle vergessen, ist der Bestand widersprüchlich. | Petra Lang heißt nach der Heirat Petra Roos → in K1 und K3 ändern; wird K3 vergessen, gibt es zwei Namen für L7. |
| Löschanomalie | Beim Löschen eines Datensatzes gehen ungewollt weitere Informationen verloren. | Wird Kurs K2 gelöscht, ist auch jede Information über Uwe Brandl weg. |
| NF | Regel | Typischer Verstoß | Lösung |
|---|---|---|---|
| 1NF | Alle Attributwerte sind atomar (ein Wert pro Feld), keine Wiederholungsgruppen. | „101 Mia Kramer, 102 Noah Ernst“ in einem Feld; „Petra Lang“ statt Vor- und Nachname getrennt | Mehrfachwerte in eigene Zeilen bzw. eigene Tabelle; zusammengesetzte Felder zerlegen |
| 2NF | 1NF und jedes Nichtschlüsselattribut ist voll funktional vom gesamten PK abhängig. | Teilnahme(KursNr, SchuelerNr, Kurstitel): Kurstitel hängt nur von KursNr ab | teilabhängige Attribute mit ihrem Teilschlüssel in eine eigene Tabelle |
| 3NF | 2NF und kein Nichtschlüsselattribut hängt transitiv (über ein anderes Nichtschlüsselattribut) vom PK ab. | Kurs(KursNr, LehrerNr, Lehrer): Lehrer hängt von LehrerNr ab | transitiv abhängige Attribute in eigene Tabelle; das „Zwischenattribut“ wird dort PK und bleibt in der Ursprungstabelle als FK |
1NF: Je Kurs und Teilnehmer eine eigene Zeile, Namen zerlegt. Schlüssel: (KursNr, SchuelerNr).
Kursliste(KursNr, SchuelerNr, Kurstitel, LehrerNr, LehrerVorname, LehrerNachname, Raum, SchuelerVorname, SchuelerNachname)
2NF: Kurstitel, LehrerNr, Lehrername und Raum hängen nur von KursNr ab, die Schülernamen nur von SchuelerNr → auslagern.
Kurs(KursNr, Kurstitel, LehrerNr, LehrerVorname, LehrerNachname, Raum)
Schueler(SchuelerNr, Vorname, Nachname)
Belegung(↑KursNr, ↑SchuelerNr)
3NF: In Kurs hängen die Lehrernamen transitiv über LehrerNr vom PK ab → eigene Tabelle.
Lehrkraft(LehrerNr, Vorname, Nachname)
Kurs(KursNr, Kurstitel, Raum, ↑LehrerNr)
Schueler(SchuelerNr, Vorname, Nachname)
Belegung(↑KursNr, ↑SchuelerNr)
Hätte ein Raum weitere Eigenschaften (Größe, Etage), bekäme auch er eine eigene Tabelle Raum(RaumNr, …) und Kurs einen FK RaumNr.
| MitgliedNr | Vorname | Nachname | Ort | Eintritt |
|---|---|---|---|---|
| 1 | Anna | Berg | Bonn | 2024-01-15 |
| 2 | Ben | Kurz | Köln | 2025-03-01 |
| 3 | Cem | Aydin | Bonn | 2025-09-10 |
| 4 | Dana | Wolf | Siegburg | 2026-02-01 |
| TrainerNr | Name |
|---|---|
| 1 | Lisa Stein |
| 2 | Omar Haddad |
| 3 | Jan Ott |
| KursNr | Titel | TrainerNr | Preis |
|---|---|---|---|
| 10 | Yoga | 1 | 8.00 |
| 11 | Spinning | 2 | 10.00 |
| 12 | Pilates | 1 | 9.00 |
| 13 | Boxen | NULL | 12.00 |
| BuchungNr | MitgliedNr | KursNr | Datum |
|---|---|---|---|
| 1 | 1 | 10 | 2026-03-02 |
| 2 | 1 | 11 | 2026-03-04 |
| 3 | 2 | 10 | 2026-03-02 |
| 4 | 3 | 11 | 2026-04-07 |
| 5 | 1 | 10 | 2026-04-06 |
| 6 | 2 | 12 | 2026-04-08 |
Vorkommen: 9/9 · Prüfungen: alle · Teil 2, Aufgabe 4 (die SQL-Aufgabe ist in allen 9 Prüfungen Aufgabe 4 von Teil 2)
SELECT Spalten / Ausdrücke [AS Alias] -- was wird angezeigt? FROM Tabelle [Alias] [INNER | LEFT] JOIN Tabelle2 ON Bedingung WHERE Bedingung für einzelne Zeilen GROUP BY Spalten HAVING Bedingung für Gruppen ORDER BY Spalte [ASC | DESC], …;
| Operator | Beispiel | Bedeutung |
|---|---|---|
= <> < > <= >= | Preis >= 9 | Vergleich (<> = ungleich) |
AND, OR, NOT | Ort = 'Bonn' AND Eintritt >= '2025-01-01' | Verknüpfung; AND bindet stärker als OR → Klammern setzen |
BETWEEN … AND … | Datum BETWEEN '2026-03-01' AND '2026-03-31' | Bereich, beide Grenzen inklusive |
IN (…) | Ort IN ('Bonn', 'Köln') | einer der aufgezählten Werte |
LIKE | Nachname LIKE 'B%', Code LIKE 'A_7%' | Muster: % = beliebig viele Zeichen (auch keins), _ = genau ein Zeichen |
IS NULL / IS NOT NULL | TrainerNr IS NULL | prüft auf „kein Wert“ – niemals = NULL |
Texte und Datumswerte stehen in einfachen Anführungszeichen, Zahlen ohne. Dezimalpunkt statt Komma (9.50). Datumsliterale im Format 'JJJJ-MM-TT'.
| Funktion (MySQL) | Ergebnis |
|---|---|
YEAR(d), MONTH(d), DAY(d) | Jahr, Monat (1–12), Tag aus einem Datum |
CURDATE(), NOW() | heutiges Datum bzw. Datum mit Uhrzeit |
DATEDIFF(d1, d2) | Anzahl Tage d1 − d2 (DATEDIFF('2026-04-08', '2026-04-06') = 2) |
Preis * 10 AS Zehnerkarte | berechnete Spalte mit Alias |
Dialekt-Hinweis: Im IHK-Belegsatz (z. B. S22) steht DATEDIFF(Datumsteil, Anfangsdatum, Enddatum) sowie TODAY/CURRENT (SQL-Server-Stil). Verwende in der Prüfung die Schreibweise aus dem Belegsatz deiner Prüfung; sinnvolle Varianten werden akzeptiert.
SELECT Nachname, Ort, YEAR(Eintritt) AS Jahr FROM Mitglied WHERE YEAR(Eintritt) >= 2025 AND (Ort = 'Bonn' OR Ort = 'Siegburg') ORDER BY Eintritt;
| Nachname | Ort | Jahr |
|---|---|---|
| Aydin | Bonn | 2025 |
| Wolf | Siegburg | 2026 |
SELECT Titel, Preis, Preis * 10 AS Zehnerkarte, Preis * 10 * 0.9 AS ZehnerkarteRabatt FROM Kurs WHERE Titel LIKE '%ing%' OR Titel LIKE 'Y%';
| Titel | Preis | Zehnerkarte | ZehnerkarteRabatt |
|---|---|---|---|
| Yoga | 8.00 | 80.00 | 72.00 |
| Spinning | 10.00 | 100.00 | 90.00 |
Ein JOIN verbindet Tabellen über ihre Beziehung, fast immer FK = PK. Fehlt die ON-Bedingung, entsteht das kartesische Produkt (jede Zeile mit jeder).
| JOIN-Art | liefert |
|---|---|
[INNER] JOIN | nur Zeilen, die auf beiden Seiten einen Partner haben |
LEFT [OUTER] JOIN | alle Zeilen der linken Tabelle (vor dem JOIN), dazu die passenden der rechten; fehlt ein Partner, sind die rechten Spalten NULL |
RIGHT [OUTER] JOIN | umgekehrt: alle Zeilen der rechten Tabelle (selten nötig – man kann die Tabellen tauschen und LEFT JOIN nehmen) |
SELECT k.Titel, t.Name FROM Kurs k INNER JOIN Trainer t ON t.TrainerNr = k.TrainerNr; -- bzw. LEFT JOIN / RIGHT JOIN
INNER JOIN (Boxen fehlt)
| Titel | Name |
|---|---|
| Yoga | Lisa Stein |
| Spinning | Omar Haddad |
| Pilates | Lisa Stein |
LEFT JOIN (alle Kurse)
| Titel | Name |
|---|---|
| Yoga | Lisa Stein |
| Spinning | Omar Haddad |
| Pilates | Lisa Stein |
| Boxen | NULL |
RIGHT JOIN (alle Trainer)
| Titel | Name |
|---|---|
| Yoga | Lisa Stein |
| Pilates | Lisa Stein |
| Spinning | Omar Haddad |
| NULL | Jan Ott |
Mehrere Tabellen verbindet man als Kette entlang der Fremdschlüssel. Tabellenaliase (m, b, k) sparen Schreibarbeit und machen Spaltennamen eindeutig:
SELECT m.Nachname, k.Titel, b.Datum FROM Mitglied m INNER JOIN Buchung b ON b.MitgliedNr = m.MitgliedNr INNER JOIN Kurs k ON k.KursNr = b.KursNr WHERE m.Ort = 'Bonn' ORDER BY b.Datum;
| Nachname | Titel | Datum |
|---|---|---|
| Berg | Yoga | 2026-03-02 |
| Berg | Spinning | 2026-03-04 |
| Berg | Yoga | 2026-04-06 |
| Aydin | Spinning | 2026-04-07 |
Die ältere Schreibweise FROM Mitglied m, Buchung b, Kurs k WHERE b.MitgliedNr = m.MitgliedNr AND … ist gleichwertig zum INNER JOIN und wird akzeptiert. Für einen LEFT JOIN braucht man aber die JOIN-Syntax.
Aufgabe: „Alle Mitglieder mit ihren Buchungen im April – auch Mitglieder ohne April-Buchung sollen erscheinen.“
Richtig – Bedingung in ON
SELECT m.Nachname, b.Datum
FROM Mitglied m
LEFT JOIN Buchung b
ON b.MitgliedNr = m.MitgliedNr
AND MONTH(b.Datum) = 4
ORDER BY m.Nachname;
| Nachname | Datum |
|---|---|
| Aydin | 2026-04-07 |
| Berg | 2026-04-06 |
| Kurz | 2026-04-08 |
| Wolf | NULL |
Falsch – Bedingung in WHERE
SELECT m.Nachname, b.Datum
FROM Mitglied m
LEFT JOIN Buchung b
ON b.MitgliedNr = m.MitgliedNr
WHERE MONTH(b.Datum) = 4
ORDER BY m.Nachname;
| Nachname | Datum |
|---|---|
| Aydin | 2026-04-07 |
| Berg | 2026-04-06 |
| Kurz | 2026-04-08 |
WHERE wird nach dem Join ausgewertet. Für „Wolf“ ist b.Datum NULL, MONTH(NULL) = 4 ist nicht wahr → die Zeile fällt heraus. Der LEFT JOIN wirkt dann wie ein INNER JOIN. Ebenso würden Mitglieder fehlen, die nur im März gebucht haben.
= NULL statt IS NULL – liefert nie ein Ergebnis.Ort = 'Bonn' OR Ort = 'Köln' AND Preis > 9 bedeutet Ort = 'Bonn' OR (Ort = 'Köln' AND Preis > 9).BETWEEN '…-01' AND '…-31' den letzten Tag nur bis 00:00 Uhr; sicherer ist >= '2026-03-01' AND < '2026-04-01'.Vorkommen: 8/9 · Prüfungen: alle außer W24 · Teil 2, Aufgabe 4
| Funktion | liefert | NULL-Werte |
|---|---|---|
COUNT(*) | Anzahl Zeilen | werden mitgezählt |
COUNT(Spalte) | Anzahl Werte in der Spalte | werden nicht gezählt |
COUNT(DISTINCT Spalte) | Anzahl verschiedener Werte | nicht gezählt |
SUM, AVG | Summe, Durchschnitt | ignoriert (AVG teilt nur durch die Anzahl der Nicht-NULL-Werte) |
MIN, MAX | kleinster, größter Wert (auch bei Text und Datum) | ignoriert |
SELECT COUNT(*) AS Anzahl, MIN(Preis) AS Min, MAX(Preis) AS Max,
SUM(Preis) AS Summe, AVG(Preis) AS Schnitt
FROM Kurs;
| Anzahl | Min | Max | Summe | Schnitt |
|---|---|---|---|---|
| 4 | 8.00 | 12.00 | 39.00 | 9.7500 |
SELECT COUNT(*) AS alle, COUNT(TrainerNr) AS mitTrainer, COUNT(DISTINCT TrainerNr) AS versch FROM Kurs;
| alle | mitTrainer | versch |
|---|---|---|
| 4 | 3 | 2 |
Ohne GROUP BY fasst eine Aggregatfunktion die ganze (gefilterte) Tabelle zu einer Zeile zusammen. Mit GROUP BY entsteht je Gruppe eine Zeile.
Beispiel: Anzahl Buchungen je Kurs – auch Kurse ohne Buchung:
SELECT k.Titel, COUNT(b.BuchungNr) AS Anzahl, COUNT(*) AS Zeilen FROM Kurs k LEFT JOIN Buchung b ON b.KursNr = k.KursNr GROUP BY k.KursNr, k.Titel ORDER BY Anzahl DESC;
| Titel | Anzahl | Zeilen |
|---|---|---|
| Yoga | 3 | 3 |
| Spinning | 2 | 2 |
| Pilates | 1 | 1 |
| Boxen | 0 | 1 |
„Boxen“ hat keine Buchung. Nach dem LEFT JOIN existiert trotzdem eine Zeile (mit NULL in den Buchungsspalten). COUNT(*) zählt diese Zeile mit (1), COUNT(b.BuchungNr) zählt nur echte Buchungen (0).
| WHERE | HAVING | |
|---|---|---|
| filtert | einzelne Zeilen | Gruppen |
| Zeitpunkt | vor der Gruppierung | nach der Gruppierung |
| Aggregatfunktionen erlaubt? | nein | ja |
| Beispiel | WHERE YEAR(b.Datum) = 2026 | HAVING COUNT(*) >= 2 |
SELECT m.MitgliedNr, m.Nachname, COUNT(*) AS Buchungen FROM Mitglied m INNER JOIN Buchung b ON b.MitgliedNr = m.MitgliedNr WHERE YEAR(b.Datum) = 2026 -- Zeilenfilter GROUP BY m.MitgliedNr, m.Nachname HAVING COUNT(*) >= 2; -- Gruppenfilter
| MitgliedNr | Nachname | Buchungen |
|---|---|---|
| 1 | Berg | 3 |
| 2 | Kurz | 2 |
COUNT(Spalte der rechten Tabelle).ORDER BY Anzahl DESC (Alias) oder ORDER BY COUNT(*) DESC.WHERE COUNT(*) > 2) → Syntaxfehler, gehört in HAVING.COUNT(*) nach LEFT JOIN liefert 1 statt 0.AVG(COALESCE(Spalte, 0)).COUNT(*) / 12 (S23).HAVING COUNT(…) > 50; W25 T2 4c (5 P): HAVING COUNT(*) >= 3.Vorkommen: 7/9 · Prüfungen: W21, S22, W22, W23, S24, W25, S26 · Teil 2, Aufgabe 4
INSERT INTO Mitglied (MitgliedNr, Vorname, Nachname, Ort, Eintritt) VALUES (5, 'Eva', 'Lorenz', 'Bonn', '2026-10-01'); -- mehrere Zeilen auf einmal INSERT INTO Trainer (TrainerNr, Name) VALUES (4, 'Kai Brehm'), (5, 'Ina Vogt');
'…', Zahlen ohne, NULL ohne Anführungszeichen.AUTO_INCREMENT lässt man weg – das DBMS vergibt die Nummer.UPDATE Kurs SET Preis = Preis * 1.05 -- Preis um 5 % erhöhen WHERE TrainerNr = 1; -- mit Unterabfrage (die Nummer ist nicht bekannt, nur der Name) UPDATE Kurs SET Preis = Preis - 1 WHERE TrainerNr = (SELECT TrainerNr FROM Trainer WHERE Name = 'Omar Haddad'); -- MySQL-Variante: UPDATE mit JOIN UPDATE Kurs k INNER JOIN Trainer t ON t.TrainerNr = k.TrainerNr SET k.Preis = k.Preis - 1 WHERE t.Name = 'Omar Haddad';
UPDATE und DELETE ohne WHERE betreffen alle Zeilen der Tabelle. Mehrere Spalten trennt man im SET mit Komma: SET Preis = 9.50, TrainerNr = 2.DELETE FROM Buchung WHERE Datum < '2026-04-01';
Referenzielle Integrität: Ein Datensatz, auf den noch ein Fremdschlüssel zeigt, kann (ohne ON DELETE CASCADE) nicht gelöscht werden. Deshalb gilt:
-- Mitglied 2 vollständig löschen DELETE FROM Buchung WHERE MitgliedNr = 2; -- 1. Kind DELETE FROM Mitglied WHERE MitgliedNr = 2; -- 2. Eltern
| Befehl | Wirkung |
|---|---|
DELETE FROM t WHERE … | löscht ausgewählte Zeilen (DML), Struktur bleibt |
TRUNCATE TABLE t | leert die ganze Tabelle schnell (DDL), Struktur bleibt |
DROP TABLE t | löscht die Tabelle samt Struktur und Daten |
Alte Datensätze werden aus der Arbeitstabelle in eine Archivtabelle verschoben: Die Arbeitstabelle bleibt klein und schnell, die Historie bleibt erhalten.
START TRANSACTION; INSERT INTO Buchung_Archiv (BuchungNr, MitgliedNr, KursNr, Datum) SELECT BuchungNr, MitgliedNr, KursNr, Datum FROM Buchung WHERE Datum < '2026-04-01'; DELETE FROM Buchung WHERE Datum < '2026-04-01'; COMMIT;
VALUES.Hat die Archivtabelle eine andere Struktur (Klartext statt Fremdschlüssel, berechnete Werte), wird im SELECT gejoint und gerechnet:
INSERT INTO Kurs_Archiv (KursNr, Titel, Trainer, AnzahlBuchungen) SELECT k.KursNr, k.Titel, t.Name, COUNT(b.BuchungNr) FROM Kurs k LEFT JOIN Trainer t ON t.TrainerNr = k.TrainerNr LEFT JOIN Buchung b ON b.KursNr = k.KursNr WHERE k.KursNr = 12 GROUP BY k.KursNr, k.Titel, t.Name;
| KursNr | Titel | Trainer | AnzahlBuchungen |
|---|---|---|---|
| 12 | Pilates | Lisa Stein | 1 |
VALUES und SELECT kombiniert – bei INSERT…SELECT steht nur das SELECT.Ende < '2026-01-01' erfasst keine Zeilen mit Ende = NULL (meist gewollt: laufende Vorgänge bleiben).9,50) statt Dezimalpunkt (9.50).Vorkommen: 6/9 · Prüfungen: S22, W22, S23, W23, W24, W25 · meist Teil 1
Eine Transaktion ist eine Folge von Datenbankoperationen, die als logische Einheit ganz oder gar nicht ausgeführt wird. START TRANSACTION beginnt sie, COMMIT macht die Änderungen dauerhaft, ROLLBACK nimmt alle Änderungen seit Beginn zurück.
Beispiel: Ein Mitglied wird von Kurs A nach Kurs B umgebucht (DELETE der alten + INSERT der neuen Buchung). Fällt nach dem DELETE der Server aus, wäre das Mitglied ohne Transaktion in gar keinem Kurs mehr.
| Eigenschaft | Bedeutung | Beispiel Fitnessstudio |
|---|---|---|
| Atomicity – Atomarität | alles oder nichts; bei Fehler wird alles zurückgesetzt | Umbuchung wird komplett oder gar nicht ausgeführt |
| Consistency – Konsistenz | Die DB geht von einem konsistenten in einen konsistenten Zustand über; alle Integritätsbedingungen (PK, FK, CHECK) sind danach erfüllt. | keine Buchung auf einen nicht existierenden Kurs |
| Isolation | Gleichzeitig laufende Transaktionen beeinflussen sich nicht – das Ergebnis ist so, als liefen sie nacheinander. | Zwei Mitglieder buchen gleichzeitig den letzten freien Platz → nur eines bekommt ihn. |
| Durability – Dauerhaftigkeit | Nach dem COMMIT bleiben die Änderungen erhalten, auch bei Absturz oder Stromausfall. | Bestätigte Buchung ist nach dem Neustart noch da. |
Jeder Fremdschlüsselwert muss als Primärschlüsselwert in der referenzierten Tabelle existieren (oder NULL sein, wenn erlaubt). Das DBMS verhindert daher
| Regel | Wirkung beim Löschen des Eltern-Datensatzes |
|---|---|
ON DELETE RESTRICT / NO ACTION | Löschen wird verweigert (Standard) |
ON DELETE CASCADE | abhängige Datensätze werden automatisch mitgelöscht |
ON DELETE SET NULL | FK in den abhängigen Datensätzen wird auf NULL gesetzt |
FOREIGN KEY (TrainerNr) REFERENCES Trainer (TrainerNr) ON DELETE SET NULL
Ein Index ist eine zusätzliche, sortierte Datenstruktur (meist ein B-Baum) über eine oder mehrere Spalten – vergleichbar mit dem Stichwortverzeichnis eines Buches. Ohne Index muss das DBMS bei einer Suche die ganze Tabelle lesen (Full Table Scan).
| Vorteile | Nachteile |
|---|---|
| schnelleres Suchen (WHERE), Verknüpfen (JOIN) und Sortieren (ORDER BY) UNIQUE-Index stellt Eindeutigkeit sicher | zusätzlicher Speicherplatz INSERT, UPDATE und DELETE werden langsamer, weil der Index mitgepflegt werden muss |
Sinnvoll für Spalten, die oft in WHERE, JOIN (Fremdschlüssel!) oder ORDER BY vorkommen, bei großen Tabellen und Spalten mit vielen verschiedenen Werten. Wenig sinnvoll bei kleinen Tabellen, bei Spalten mit wenigen verschiedenen Werten (z. B. ja/nein) und bei Tabellen mit sehr vielen Schreibzugriffen. Der Primärschlüssel ist automatisch indiziert.
CREATE INDEX idx_buchung_datum ON Buchung (Datum);
Siehe DB-02. Ergänzung: Gewollte Redundanz gibt es z. B. in Archiv- und Auswertungstabellen (Data Warehouse), bei bewusster Denormalisierung für schnellere Abfragen und bei Datensicherungen.
NoSQL („not only SQL“) bezeichnet Datenbanken ohne festes Tabellenschema. Arten: Dokumentenorientiert (JSON-Dokumente, z. B. MongoDB), Key-Value (Schlüssel → Wert, z. B. Cache, Sitzungsdaten), spaltenorientiert (Wide Column, sehr große verteilte Datenmengen), Graph (Knoten und Kanten, z. B. soziale Netze, Routen).
| Relational | Dokumentenorientiert |
|---|---|
| Tabelle | Collection (Sammlung) |
| Zeile / Datensatz | Document (Dokument) |
| Spalte / Attribut | Field (Feld, Schlüssel-Wert-Paar) |
| Primärschlüssel | _id (Dokument-ID) |
| Fremdschlüssel + JOIN | Referenz (gespeicherte ID eines anderen Dokuments) oder Einbettung (Embedding) |
Einbettung vs. Referenz am Beispiel „Mitglied mit Buchungen“:
Einbettung (Embedding)
{
"_id": 1,
"vorname": "Anna",
"nachname": "Berg",
"ort": "Bonn",
"buchungen": [
{ "datum": "2026-03-02", "kurs": "Yoga" },
{ "datum": "2026-03-04", "kurs": "Spinning" }
]
}Referenz
// Collection "mitglieder"
{ "_id": 1, "vorname": "Anna",
"nachname": "Berg", "ort": "Bonn" }
// Collection "buchungen"
{ "_id": 1, "mitgliedId": 1,
"kursId": 10, "datum": "2026-03-02" }| Einbettung | Referenz | |
|---|---|---|
| Vorteil | ein Lesezugriff liefert alles; Änderung eines Dokuments ist atomar | keine Duplikate; Daten unabhängig voneinander änderbar |
| Nachteil | Daten werden dupliziert (Kursname in vielen Dokumenten); Dokumente wachsen | mehrere Abfragen bzw. Verknüpfung (Lookup) nötig |
| geeignet für | „gehört zu“, wird zusammen gelesen, 1:wenige | m:n, große oder unabhängig geänderte Daten |
JSON-Regeln: Objekt { "schlüssel": wert, … }, Array [ wert, wert ]; Schlüssel und Strings in doppelten Anführungszeichen; Zahlen, true, false, null ohne; kein Komma nach dem letzten Element; Datum als String.
| Kriterium | Relationale DB | Dokumentenorientierte DB |
|---|---|---|
| Schema | fest, vorab definiert | flexibel, Dokumente einer Collection dürfen unterschiedlich aufgebaut sein |
| Struktur | normalisierte Tabellen | verschachtelte Dokumente |
| Beziehungen | FK + JOIN | Einbettung oder Referenz, kaum Joins |
| Konsistenz | ACID über beliebig viele Tabellen | oft nur je Dokument atomar; verteilt häufig „eventual consistency“ (BASE) |
| Skalierung | eher vertikal (größerer Server) | horizontal (viele Server, Sharding) |
| Abfrage | standardisiertes SQL | produktspezifische Abfragesprache/API |
| typischer Einsatz | Buchhaltung, Verwaltung, viele Beziehungen, strenge Konsistenz | große, wechselnd strukturierte Datenmengen: Logs, Sensordaten, Kataloge, Inhalte |
Vorkommen: 5/9 · Prüfungen: W21, S22, W22, W23, S26 · Teil 2, Aufgabe 4
Eine Unterabfrage (Subquery) ist ein SELECT in Klammern innerhalb einer anderen Anweisung (SELECT, UPDATE, DELETE, INSERT).
| Art | liefert | verwendet mit |
|---|---|---|
| skalare Unterabfrage | genau einen Wert | = < > …, auch im SELECT oder SET |
| Listen-Unterabfrage | eine Spalte, mehrere Zeilen | IN, NOT IN |
| EXISTS-Unterabfrage | wahr/falsch (gibt es mindestens eine Zeile?) | EXISTS, NOT EXISTS |
| Tabellen-Unterabfrage | eine (Zwischen-)Tabelle | in FROM (…) AS alias |
Vergleich mit einem Aggregat – Kurse, die teurer sind als der Durchschnitt:
SELECT Titel, Preis FROM Kurs WHERE Preis > (SELECT AVG(Preis) FROM Kurs);
| Titel | Preis |
|---|---|
| Spinning | 10.00 |
| Boxen | 12.00 |
IN – Mitglieder, die Spinning (Kurs 11) gebucht haben:
SELECT Nachname FROM Mitglied WHERE MitgliedNr IN (SELECT MitgliedNr FROM Buchung WHERE KursNr = 11);
| Nachname |
|---|
| Berg |
| Aydin |
NOT EXISTS – Mitglieder ohne jede Buchung:
SELECT m.Nachname FROM Mitglied m WHERE NOT EXISTS (SELECT * FROM Buchung b WHERE b.MitgliedNr = m.MitgliedNr);
| Nachname |
|---|
| Wolf |
m.MitgliedNr) und wird gedanklich für jede Zeile der äußeren Abfrage neu ausgeführt (Beispiel NOT EXISTS oben).Korreliertes Beispiel – die jeweils letzte Buchung jedes Mitglieds:
SELECT b.BuchungNr, b.MitgliedNr, b.Datum
FROM Buchung b
WHERE b.Datum = (SELECT MAX(b2.Datum)
FROM Buchung b2
WHERE b2.MitgliedNr = b.MitgliedNr)
ORDER BY b.MitgliedNr;
| BuchungNr | MitgliedNr | Datum |
|---|---|---|
| 5 | 1 | 2026-04-06 |
| 6 | 2 | 2026-04-08 |
| 4 | 3 | 2026-04-07 |
Unterabfrage in FROM – „Wie viele Buchungen hat der meistgebuchte Kurs?“ (Aggregat über ein Aggregat):
SELECT MAX(Anzahl) AS Maximum
FROM (SELECT KursNr, COUNT(*) AS Anzahl
FROM Buchung
GROUP BY KursNr) AS tbl;
| Maximum |
|---|
| 3 |
Alternative zu NOT IN/NOT EXISTS: LEFT JOIN … WHERE rechts.PK IS NULL (alle linken Zeilen ohne Partner).
= statt IN, obwohl die Unterabfrage mehrere Zeilen liefert → Laufzeitfehler.NOT IN keine einzige Zeile. Beispiel: „Trainer ohne Kurs“ mit WHERE TrainerNr NOT IN (SELECT TrainerNr FROM Kurs) ergibt eine leere Menge, weil Kurs „Boxen“ die TrainerNr NULL hat. NOT EXISTS (oder … WHERE TrainerNr IS NOT NULL in der Unterabfrage) liefert korrekt „Jan Ott“.WHERE Preis > AVG(Preis)) – geht nicht, dafür braucht man die Unterabfrage.Vorkommen: 5/9 · Prüfungen: W21, S22, W22, W25, S26 · Teil 2, Aufgabe 3/4
| Teilsprache | Zweck | Befehle |
|---|---|---|
| DDL – Data Definition Language | Struktur definieren | CREATE, ALTER, DROP (auch TRUNCATE) |
| DML – Data Manipulation Language | Daten bearbeiten (und abfragen) | INSERT, UPDATE, DELETE, SELECT (SELECT wird teils als DQL – Data Query Language – geführt) |
| DCL – Data Control Language | Rechte vergeben/entziehen | GRANT, REVOKE |
| TCL – Transaction Control Language | Transaktionen steuern | COMMIT, ROLLBACK |
CRUD (Create, Read, Update, Delete) sind die vier Grundoperationen auf Daten: Create → INSERT, Read → SELECT, Update → UPDATE, Delete → DELETE – also alles DML. (Nicht verwechseln: CREATE TABLE und DROP TABLE sind DDL.)
| Datentyp | Verwendung | Beispiel |
|---|---|---|
INTEGER (INT) | Ganzzahlen, IDs, Mengen | MitgliedNr, Anzahl |
DECIMAL(p,s) | exakte Festkommazahl: p Stellen insgesamt, davon s Nachkommastellen – für Geld | Preis DECIMAL(6,2) → max. 9999.99 |
DOUBLE / FLOAT | Gleitkommazahl (Rundungsfehler möglich) – für Messwerte | Temperatur, Koordinaten |
CHAR(n) | Text fester Länge | Ländercode CHAR(2) |
VARCHAR(n) | Text variabler Länge (höchstens n Zeichen) | Nachname VARCHAR(40) |
TEXT | lange Texte | Bemerkung |
DATE, TIME, DATETIME | Datum, Uhrzeit, beides | Eintritt DATE |
BOOLEAN | wahr/falsch (in MySQL intern TINYINT(1)) | aktiv |
| Constraint | Bedeutung |
|---|---|
PRIMARY KEY (Spalte[, …]) | Primärschlüssel (eindeutig, nicht NULL); mehrere Spalten = zusammengesetzter PK |
FOREIGN KEY (Spalte) REFERENCES Tabelle (Spalte) | Fremdschlüssel (referenzielle Integrität) |
NOT NULL | Pflichtfeld |
UNIQUE | Wert darf nur einmal vorkommen (NULL ist mehrfach erlaubt) |
DEFAULT Wert | Standardwert, wenn beim INSERT nichts angegeben wird |
CHECK (Bedingung) | Wertebereich prüfen, z. B. CHECK (Preis >= 0) |
AUTO_INCREMENT (MySQL) | fortlaufende Nummer automatisch vergeben |
CREATE TABLE Kurs ( KursNr INTEGER NOT NULL, Titel VARCHAR(30) NOT NULL UNIQUE, TrainerNr INTEGER, -- darf NULL sein Preis DECIMAL(5,2) NOT NULL DEFAULT 8.00, MaxPlaetze INTEGER CHECK (MaxPlaetze > 0), PRIMARY KEY (KursNr), FOREIGN KEY (TrainerNr) REFERENCES Trainer (TrainerNr) );
Reihenfolge: Die referenzierte Tabelle (Trainer) muss vorher existieren; beim Löschen mit DROP TABLE umgekehrt. Der Datentyp des FK muss zum PK passen. Zusammengesetzter PK: PRIMARY KEY (MitgliedNr, KursNr, Datum).
ALTER TABLE Mitglied ADD COLUMN Email VARCHAR(80); ALTER TABLE Mitglied DROP COLUMN Ort; ALTER TABLE Mitglied MODIFY COLUMN Nachname VARCHAR(60) NOT NULL; -- MySQL ALTER TABLE Mitglied ADD CONSTRAINT uq_mitglied_email UNIQUE (Email); ALTER TABLE Kurs ADD FOREIGN KEY (TrainerNr) REFERENCES Trainer (TrainerNr); DROP TABLE Buchung_Alt; CREATE INDEX idx_mitglied_nachname ON Mitglied (Nachname);
Spalte aus vorhandenen Daten ableiten (Muster aus W25): neue Spalte anlegen → per UPDATE mit Textfunktion füllen → ggf. alte Spalte löschen. Beispiel: Die ersten zwei Zeichen eines Mitgliedscodes wie 'BN-2024-001' geben den Standort an:
ALTER TABLE Mitglied ADD COLUMN Standort CHAR(2); UPDATE Mitglied SET Standort = LEFT(Mitgliedscode, 2); -- oder SUBSTRING(Mitgliedscode, 1, 2)
Textfunktionen (MySQL): LEFT(t, n), RIGHT(t, n), SUBSTRING(t, start, länge) (Zählung ab 1), LENGTH(t), CONCAT(t1, t2, …), UPPER(t)/LOWER(t), TRIM(t).
DROP TABLE statt DELETE – DROP löscht die ganze Tabelle.Vorkommen: 1/9 · Prüfung: S24 (T2 4d, 12 P)
UNION hängt die Ergebnisse zweier SELECT-Anweisungen untereinander (ein JOIN verbindet dagegen nebeneinander).
ORDER BY steht nur einmal ganz am Ende und sortiert das Gesamtergebnis.| UNION | UNION ALL | |
|---|---|---|
| Duplikate | werden entfernt (wie DISTINCT) | bleiben erhalten |
| Geschwindigkeit | langsamer (Vergleich aller Zeilen) | schneller |
| verwenden, wenn … | eine Liste ohne Wiederholungen gewünscht ist | jede Zeile ein eigener Datensatz ist, der gezählt/summiert werden soll |
SELECT Nachname AS Name, 'Mitglied' AS Rolle FROM Mitglied WHERE Ort = 'Bonn' UNION SELECT Name, 'Trainer' FROM Trainer ORDER BY Name;
| Name | Rolle |
|---|---|
| Aydin | Mitglied |
| Berg | Mitglied |
| Jan Ott | Trainer |
| Lisa Stein | Trainer |
| Omar Haddad | Trainer |
Typisches Muster: aktuelle Tabelle + Archivtabelle gemeinsam auswerten. Soll über die vereinigte Menge gruppiert werden, kommt die UNION in eine Unterabfrage in FROM:
SELECT Jahr, COUNT(*) AS Anzahl
FROM (SELECT YEAR(Datum) AS Jahr FROM Buchung
UNION ALL
SELECT YEAR(Datum) FROM Buchung_Archiv) AS alle
GROUP BY Jahr
ORDER BY Jahr;
Sind die Gruppen in den beiden Tabellen sicher getrennt (z. B. alle alten Jahre nur im Archiv), kann man auch jede Tabelle einzeln gruppieren und die beiden Gruppenergebnisse mit UNION ALL verbinden. Überschneiden sich die Gruppen, entstehen dabei aber zwei Ergebniszeilen für dieselbe Gruppe.
UNION ALL, GROUP BY YEAR(…) und ORDER BY … DESC. Vorher (4c) wurde ins Archiv verschoben – die Aufgaben bauen aufeinander auf.Vorkommen: 1/9 · Prüfung: S23 (T2 4d, 4 P)
CREATE USER rezeption IDENTIFIED BY 'Passwort'; -- MySQL genauer: 'rezeption'@'localhost' GRANT SELECT, INSERT, UPDATE ON fitness.Mitglied TO rezeption; GRANT SELECT ON fitness.Kurs TO rezeption; -- je Tabelle ein GRANT (oder fitness.* für alle) REVOKE UPDATE ON fitness.Mitglied FROM rezeption; CREATE ROLE trainer_rolle; -- Rolle = Bündel von Rechten GRANT SELECT ON fitness.* TO trainer_rolle; GRANT trainer_rolle TO lisa; -- Benutzer erhält die Rolle DROP USER rezeption;
| Recht | erlaubt |
|---|---|
SELECT, INSERT, UPDATE, DELETE | lesen, einfügen, ändern, löschen (UPDATE auch spaltenweise: GRANT UPDATE (Email) ON …) |
ALL PRIVILEGES | alle Rechte auf dem Objekt |
WITH GRANT OPTION | Benutzer darf seine Rechte an andere weitergeben – nur sehr sparsam vergeben |
CREATE … IDENTIFIED BY, GRANT … ON … TO, REVOKE … ON … FROM) steht im Belegsatz.Vorkommen: 1/9 · Prüfung: S22 (T2 4aa/4ab, je 2 P)
| View (Sicht) | Stored Procedure | Trigger | |
|---|---|---|---|
| Was? | gespeicherte SELECT-Abfrage, die wie eine (virtuelle) Tabelle benutzt wird; speichert selbst keine Daten | in der Datenbank gespeicherte, benannte Folge von SQL-Anweisungen mit Parametern (auch Variablen, Verzweigungen) | SQL-Code, der automatisch bei einem Ereignis (INSERT, UPDATE, DELETE) auf einer Tabelle ausgeführt wird |
| Auslösung | SELECT * FROM v_name | expliziter Aufruf CALL name(…) | durch das Ereignis, BEFORE oder AFTER, je Zeile (FOR EACH ROW); Zugriff auf alte/neue Werte mit OLD/NEW |
| Zweck | komplexe Abfragen vereinfachen; Zugriffsschutz (nur bestimmte Spalten/Zeilen freigeben); stabile Schnittstelle trotz Tabellenänderung | Geschäftslogik zentral in der DB; weniger Netzwerkverkehr; Rechte nur auf die Prozedur statt auf Tabellen | Protokollierung (Audit), Plausibilitätsprüfungen, abgeleitete Werte aktuell halten, Integritätsregeln |
CREATE VIEW v_kursuebersicht AS SELECT k.Titel, t.Name AS Trainer, k.Preis FROM Kurs k LEFT JOIN Trainer t ON t.TrainerNr = k.TrainerNr; DELIMITER // CREATE PROCEDURE kurs_buchen(IN p_mitglied INT, IN p_kurs INT) BEGIN INSERT INTO Buchung (MitgliedNr, KursNr, Datum) VALUES (p_mitglied, p_kurs, CURDATE()); END // DELIMITER ; CALL kurs_buchen(4, 12); CREATE TRIGGER trg_preis_protokoll AFTER UPDATE ON Kurs FOR EACH ROW INSERT INTO Preis_Log (KursNr, PreisAlt, PreisNeu, Zeitpunkt) VALUES (OLD.KursNr, OLD.Preis, NEW.Preis, NOW());
Ein BEFORE-Trigger kann eine Änderung auch verhindern, in MySQL mit SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '…'. DELIMITER ist nur im MySQL-Client nötig, damit das Semikolon im Rumpf die Anweisung nicht vorzeitig beendet.
| Logik in der DB (Trigger/Procedure) | |
|---|---|
| Vorteile | gilt für alle Anwendungen, die auf die DB zugreifen; Datenintegrität unabhängig vom Client; weniger Datenübertragung; Performance |
| Nachteile | herstellerspezifische Syntax (Bindung an ein DBMS); schwerer zu testen, zu debuggen und zu versionieren; Trigger laufen „unsichtbar“ – Seiteneffekte werden leicht übersehen; Last liegt auf dem DB-Server |
Vorkommen: 1/9 · Prüfung: W24 (T2 3b, 13 P)
| Kriterium | Frage |
|---|---|
| Vollständigkeit | Sind alle Pflichtangaben vorhanden? |
| Korrektheit (Richtigkeit) | Stimmen die Werte mit der Realität überein (keine Tippfehler)? |
| Konsistenz | Sind die Daten widerspruchsfrei (gleiche Sache überall gleich)? |
| Einheitlichkeit | Sind Formate und Schreibweisen einheitlich (Datum, Zahlen, Einheiten)? |
| Eindeutigkeit | Gibt es keine Dubletten? |
| Atomarität | Steht in jedem Feld genau ein Wert? |
| Gültigkeit / Plausibilität | Liegen die Werte im zulässigen Bereich (kein 31.02., kein negativer Preis)? |
| Aktualität | Sind die Daten auf dem neuesten Stand? |
Beispiel: Mitgliederliste eines Sportvereins (Excel):
| Name | Geburtstag | Abteilung | Beitrag |
|---|---|---|---|
| Meier, Anna | 03.04.1990 | Tennis | 120 € |
| Jan Schulz | 1985 | Tennis, Fußball | 12o |
| A. Meier | 3.4.90 | Tennis | 120,00 |
| Kemal Öztürk | Fussball | frei |
| Problem | Beispiel | Folge beim Import |
|---|---|---|
| uneinheitliche Formate und Schreibweisen | 03.04.1990 / 3.4.90 / 1985; Fußball / Fussball; „120 €“ / „120,00“ | Import in DATE/DECIMAL schlägt fehl oder liefert falsche Werte; Auswertungen je Abteilung werden falsch, weil „Fussball“ als eigene Abteilung gilt |
| mehrere Werte in einem Feld (nicht atomar) | „Tennis, Fußball“; Vor- und Nachname in einem Feld, mal „Nachname, Vorname“, mal umgekehrt | keine Zuordnung zu einem Fremdschlüssel möglich; Suchen/Sortieren nach Nachname unmöglich |
| fehlende Werte | leeres Geburtsdatum | Verletzung von NOT NULL, unvollständige Datensätze |
| Dubletten | „Meier, Anna“ und „A. Meier“ | dieselbe Person doppelt im System → doppelte Rechnungen, falsche Statistik, PK-/UNIQUE-Verletzung |
| ungültige Werte, Tippfehler, Text statt Wert | „12o“ (Buchstabe o), „frei“ | Typfehler beim Import; Werte müssen per Regel übersetzt werden („frei“ → 0) |
ETL = Extract (Daten aus der Quelle lesen, z. B. CSV-Export der Excel-Datei) – Transform (bereinigen, vereinheitlichen, aufteilen, Dubletten zusammenführen, Schlüssel zuordnen, prüfen) – Load (in die Zieltabellen laden, Reihenfolge der Fremdschlüssel beachten).
Abzuwägen sind Aufwand (Datenmenge, Fehlerquote, Anteil manueller Nacharbeit) und Nutzen (Bedeutung der Historie für Auswertungen, Gewährleistung, gesetzliche Aufbewahrungspflichten, Risiko falscher Daten im neuen System). Mögliche Ergebnisse: vollständiger Import nach Bereinigung, Teilimport (z. B. nur Stammdaten oder nur die letzten Jahre) oder kein Import (Altdaten schreibgeschützt archivieren, Neuerfassung).
Enthält nur, was dir auch die IHK beilegen würde: Notationshilfen und Anlagen (Ausgangssituation, Tabellen, Formulare, Texte). Keine Erklärungen. Tipp: Diesen Teil separat ausdrucken und beim Lösen daneben legen.
| Syntax | Beschreibung |
|---|---|
| Tabellen und Objekte | |
| CREATE TABLE Tabellenname ( Spaltenname Datentyp [NOT NULL] [DEFAULT Wert] [UNIQUE], …, PRIMARY KEY (Spaltenname[, …]), FOREIGN KEY (Spaltenname) REFERENCES Tabellenname (Spaltenname), CHECK (Bedingung) ) | Erzeugt eine neue, leere Tabelle |
| ALTER TABLE Tabellenname ADD COLUMN Spaltenname Datentyp DROP COLUMN Spaltenname MODIFY COLUMN Spaltenname Datentyp ADD CONSTRAINT Name UNIQUE (Spaltenname) ADD FOREIGN KEY (Spaltenname) REFERENCES Tabellenname (Spaltenname) | Ändert die Struktur einer Tabelle: Spalte hinzufügen Spalte entfernen Datentyp ändern Eindeutigkeit festlegen Fremdschlüssel festlegen |
| DROP TABLE Tabellenname | Löscht eine Tabelle |
| CREATE [UNIQUE] INDEX Indexname ON Tabellenname (Spaltenname[, …]) | Erzeugt einen Index |
| CREATE VIEW Viewname AS SELECT … | Erzeugt eine Sicht |
| INTEGER DECIMAL(p, s) DOUBLE CHAR(n) / VARCHAR(n) DATE / DATETIME BOOLEAN | Ganzzahl Festkommazahl (p Stellen, davon s Nachkommastellen) Gleitkommazahl Text fester / variabler Länge Datum (JJJJ-MM-TT) / Datum mit Uhrzeit Wahrheitswert |
| Abfragen | |
| SELECT [DISTINCT] * | Spalte [AS Alias][, …] | Auswahl der Spalten; DISTINCT entfernt doppelte Zeilen |
| FROM Tabellenname [[AS] Alias][, …] | Tabelle(n), aus denen die Daten stammen |
| [INNER] JOIN Tabellenname ON Bedingung | Nur Datensätze mit passendem Partner in beiden Tabellen |
| LEFT [OUTER] JOIN Tabellenname ON Bedingung | Alle Datensätze der linken Tabelle und die passenden der rechten |
| RIGHT [OUTER] JOIN Tabellenname ON Bedingung | Alle Datensätze der rechten Tabelle und die passenden der linken |
| WHERE Bedingung | Auswahl von Datensätzen |
| GROUP BY Spaltenname[, …] | Gruppierung |
| HAVING Bedingung | Auswahl von Gruppen |
| ORDER BY Spaltenname [ASC | DESC][, …] | Sortierung aufsteigend / absteigend |
| SELECT … UNION [ALL] SELECT … | Vereinigung zweier Ergebnismengen (ALL: mit Duplikaten) |
| WHERE Spalte [NOT] IN (SELECT …) | Wert ist (nicht) in der Ergebnismenge der Unterabfrage |
| WHERE [NOT] EXISTS (SELECT …) | Unterabfrage liefert (k)eine Zeile |
| WHERE Spalte > (SELECT …) | Vergleich mit dem Ergebnis einer Unterabfrage |
| SELECT … FROM (SELECT … ) AS tbl | Unterabfrage als Tabelle |
| Datenmanipulation | |
| INSERT INTO Tabellenname [(Spalte1, Spalte2, …)] VALUES (Wert1, Wert2, …)[, (…)] oder SELECT … FROM … WHERE … | Fügt Datensätze ein – mit festen Werten oder als Ergebnis einer Abfrage |
| UPDATE Tabellenname SET Spalte = Wert[, …] [WHERE Bedingung] | Ändert Datensätze |
| DELETE FROM Tabellenname [WHERE Bedingung] | Löscht Datensätze |
| START TRANSACTION / COMMIT / ROLLBACK | Transaktion beginnen / bestätigen / zurücksetzen |
| Berechtigungen | |
| CREATE USER Benutzer IDENTIFIED BY 'Passwort' CREATE ROLE Rolle | Erzeugt einen Benutzer mit Passwort Erzeugt eine Rolle |
| GRANT Recht[, …] | ALL ON Datenbank.Objekt | Datenbank.* TO Benutzer | Rolle [WITH GRANT OPTION] GRANT Rolle TO Benutzer | Vergibt Rechte (SELECT, INSERT, UPDATE, DELETE) auf ein Objekt Weist einem Benutzer eine Rolle zu |
| REVOKE Recht[, …] ON Datenbank.Objekt FROM Benutzer | Rolle | Entzieht Rechte |
| Aggregatfunktionen | |
| COUNT(* | Spalte | DISTINCT Spalte) | Anzahl Zeilen / Nicht-NULL-Werte / verschiedener Werte |
| SUM(Spalte | Formel), AVG(Spalte | Formel) | Summe, arithmetisches Mittel |
| MIN(Spalte | Formel), MAX(Spalte | Formel) | kleinster, größter Wert |
| Funktionen | |
| YEAR(Datum), MONTH(Datum), DAY(Datum) | Jahr, Monat, Tag eines Datums |
| CURDATE(), NOW() | aktuelles Datum, aktuelles Datum mit Uhrzeit |
| DATEDIFF(Datum1, Datum2) | Anzahl Tage Datum1 − Datum2 |
| DATE_ADD(Datum, INTERVAL n DAY | MONTH | YEAR) | addiert ein Intervall zu einem Datum |
| LEFT(Text, n), RIGHT(Text, n) | n Zeichen von links / rechts |
| SUBSTRING(Text, Start, Länge) | Teilzeichenkette ab Position Start (erstes Zeichen = 1) |
| LENGTH(Text), CONCAT(Text1, Text2, …), UPPER(Text), LOWER(Text), TRIM(Text) | Länge, Verketten, Groß-/Kleinschreibung, Leerzeichen entfernen |
| ROUND(Zahl, n), COALESCE(Wert1, Wert2, …) | Runden auf n Stellen; erster Wert, der nicht NULL ist |
| Operatoren | |
| =, <>, <, >, <=, >= | Vergleich (<>: ungleich) |
| AND, OR, NOT | logisches UND, ODER, NICHT |
| BETWEEN Wert1 AND Wert2 | Wert im Bereich (Grenzen eingeschlossen) |
| IN (Wert1, Wert2, …) | Wert ist in der Liste enthalten |
| LIKE 'Muster' | Textvergleich mit Platzhaltern: % beliebig viele Zeichen, _ genau ein Zeichen |
| IS NULL, IS NOT NULL | Überprüfung auf NULL |
| +, −, *, / | Grundrechenarten |
Die VeloPunkt GmbH mit Sitz in Freiburg im Breisgau vermietet an fünf Stationen in Südbaden E-Bikes, E-Lastenräder und Kinderräder an Privat- und Firmenkunden. Zum Unternehmen gehören außerdem eine Werkstatt, die die eigene Flotte wartet und Fahrräder von Privatkunden repariert, sowie ein Angebot an geführten E-Bike-Touren.
Bisher werden Ausleihen, Wartungen, Schichtpläne und Kundendaten in mehreren Excel-Listen und auf Papierformularen geführt. Die DataWerk Software GmbH, Ihr Ausbildungsbetrieb, wurde beauftragt, das webbasierte Verleih- und Werkstattsystem „VeloManager“ mit Online-Buchung zu entwickeln. Kernstück ist eine relationale Datenbank (MySQL). Ein Teil der Datenbank ist bereits im Testbetrieb (Anlagen 2 und 3).
Sie arbeiten im Projektteam mit und sind für den Datenbankentwurf, die SQL-Abfragen und die Übernahme der Altdaten zuständig.
Hinweise: Heute ist der 10.10.2026. Datumswerte sind im Format JJJJ-MM-TT gespeichert, Geldbeträge in Euro.
| StationNr | Name | PLZ | Ort |
|---|---|---|---|
| 1 | Hauptbahnhof | 79098 | Freiburg |
| 2 | Messe | 79108 | Freiburg |
| 3 | Titisee | 79822 | Titisee-Neustadt |
| 4 | Kaiserstuhl | 79235 | Vogtsburg |
| 5 | Schauinsland | 79254 | Oberried |
| KategorieNr | Bezeichnung | Tagespreis |
|---|---|---|
| 1 | City-E-Bike | 25.00 |
| 2 | Trekking-E-Bike | 30.00 |
| 3 | E-Mountainbike | 39.00 |
| 4 | E-Lastenrad | 45.00 |
| 5 | Kinderrad | 12.00 |
| 6 | Tandem | 35.00 |
| FahrradNr | Rahmennummer | Modell | KategorieNr | StationNr | Kaufdatum | Kaufpreis |
|---|---|---|---|---|---|---|
| 101 | WAW-23-0017 | Urban C5 | 1 | 1 | 2023-03-15 | 2499.00 |
| 102 | WAW-23-0018 | Urban C5 | 1 | 1 | 2023-03-15 | 2499.00 |
| 103 | KTX-24-1120 | Tour T7 | 2 | 2 | 2024-04-02 | 3199.00 |
| 104 | KTX-24-1121 | Tour T7 | 2 | 3 | 2024-04-02 | 3199.00 |
| 105 | MTN-22-0456 | Trail X9 | 3 | 3 | 2022-05-20 | 4290.00 |
| 106 | MTN-25-0811 | Trail X9 | 3 | 4 | 2025-03-10 | 4490.00 |
| 107 | CRG-24-0033 | Cargo L2 | 4 | 1 | 2024-06-12 | 5390.00 |
| 108 | CRG-25-0090 | Cargo L2 | 4 | 2 | 2025-04-28 | 5590.00 |
| 109 | KID-23-0301 | Kiddy 20 | 5 | 3 | 2023-05-02 | 649.00 |
| 110 | WAW-26-0002 | Urban C6 | 1 | 4 | 2026-02-20 | 2799.00 |
| KundenNr | Vorname | Nachname | PLZ | Ort | |
|---|---|---|---|---|---|
| 1001 | Lena | Hoffmann | 79098 | Freiburg | lena.hoffmann@mail.de |
| 1002 | Jonas | Albrecht | 79102 | Freiburg | j.albrecht@web.de |
| 1003 | Mira | Schulze | 79211 | Denzlingen | NULL |
| 1004 | Paul | Wagner | 79822 | Titisee-Neustadt | paul.wagner@gmx.de |
| 1005 | Sofia | Keller | 79100 | Freiburg | s.keller@posteo.de |
| 1006 | Tim | Brandt | 77933 | Lahr | tim.brandt@mail.de |
| 1007 | Emma | Vogel | 79098 | Freiburg | NULL |
| 1008 | David | Roth | 01067 | Dresden | d.roth@web.de |
| 1009 | Hannah | Krüger | 79194 | Gundelfingen | hannah.k@gmx.de |
| 1010 | Felix | Neumann | 79108 | Freiburg | f.neumann@mail.de |
| AusleiheNr | KundenNr | FahrradNr | Beginn | Ende | Kilometer | Betrag |
|---|---|---|---|---|---|---|
| 5001 | 1001 | 101 | 2025-08-02 | 2025-08-03 | 64 | 50.00 |
| 5002 | 1002 | 105 | 2025-09-13 | 2025-09-13 | 38 | 39.00 |
| 5003 | 1004 | 107 | 2025-10-04 | 2025-10-06 | 41 | 135.00 |
| 5004 | 1001 | 103 | 2026-03-21 | 2026-03-22 | 92 | 60.00 |
| 5005 | 1003 | 109 | 2026-04-11 | 2026-04-11 | 12 | 12.00 |
| 5006 | 1005 | 107 | 2026-05-01 | 2026-05-03 | 57 | 135.00 |
| 5007 | 1002 | 106 | 2026-05-30 | 2026-06-01 | 118 | 117.00 |
| 5008 | 1006 | 104 | 2026-06-14 | 2026-06-20 | 315 | 210.00 |
| 5009 | 1001 | 108 | 2026-07-18 | 2026-07-18 | 23 | 45.00 |
| 5010 | 1006 | 105 | 2026-08-08 | 2026-08-09 | 76 | 78.00 |
| 5011 | 1007 | 102 | 2026-08-22 | 2026-08-24 | 49 | 75.00 |
| 5012 | 1005 | 103 | 2026-10-08 | NULL | NULL | NULL |
Ende, Kilometer und Betrag sind NULL, solange das Fahrrad noch nicht zurückgegeben wurde. Abholung und Rückgabe am selben Tag zählen als ein Miettag.
| WartungNr | FahrradNr | Datum | Art | Kosten |
|---|---|---|---|---|
| 1 | 101 | 2025-11-20 | Inspektion | 89.00 |
| 2 | 105 | 2025-11-25 | Bremsen | 145.50 |
| 3 | 107 | 2026-01-14 | Inspektion | 119.00 |
| 4 | 103 | 2026-02-03 | Inspektion | 89.00 |
| 5 | 105 | 2026-04-20 | Akku-Check | 35.00 |
| 6 | 109 | 2026-05-07 | Reifen | 42.90 |
| 7 | 107 | 2026-07-01 | Bremsen | 168.00 |
| 8 | 104 | 2026-09-15 | Reifen | 55.00 |
| 9 | 105 | 2026-09-30 | Inspektion | NULL |
Kosten = NULL: Werkstattauftrag noch nicht abgerechnet.
Primärschlüssel (jeweils erste Spalte): StationNr, KategorieNr, FahrradNr, KundenNr, AusleiheNr, WartungNr.
Fremdschlüssel (ohne ON DELETE CASCADE):
Fahrrad.KategorieNr → Kategorie.KategorieNr · Fahrrad.StationNr → Station.StationNr ·
Ausleihe.KundenNr → Kunde.KundenNr · Ausleihe.FahrradNr → Fahrrad.FahrradNr ·
Wartung.FahrradNr → Fahrrad.FahrradNr
Abgeschlossene Ausleihen werden regelmäßig archiviert, ausgemusterte Fahrräder in Fahrrad_Archiv übernommen. Die Archivtabellen haben keine Fremdschlüssel.
| AusleiheNr | KundenNr | FahrradNr | Beginn | Ende | Kilometer | Betrag |
|---|---|---|---|---|---|---|
| 4001 | 1001 | 101 | 2024-05-10 | 2024-05-11 | 55 | 50.00 |
| 4002 | 1009 | 105 | 2024-06-22 | 2024-06-23 | 81 | 78.00 |
| 4003 | 1002 | 102 | 2024-07-06 | 2024-07-06 | 31 | 25.00 |
| 4004 | 1004 | 109 | 2024-08-15 | 2024-08-17 | 20 | 36.00 |
| 4005 | 1009 | 107 | 2024-09-28 | 2024-09-28 | 18 | 45.00 |
| 4006 | 1006 | 103 | 2024-10-12 | 2024-10-13 | 104 | 60.00 |
| 4007 | 1003 | 104 | 2025-04-19 | 2025-04-20 | 66 | 60.00 |
| 4008 | 1001 | 101 | 2025-06-07 | 2025-06-08 | 64 | 50.00 |
| FahrradNr | Rahmennummer | Modell | Kategorie | Kaufdatum | Ausmusterung | GesamtKm |
|---|---|---|---|---|---|---|
| 95 | WAW-21-0004 | Urban C4 | City-E-Bike | 2021-04-01 | 2025-12-31 | 4120 |
| 98 | MTN-21-0102 | Trail X8 | E-Mountainbike | 2021-06-15 | 2026-01-15 | 2875 |
Kategorie enthält die Bezeichnung der Kategorie im Klartext, GesamtKm die Summe der Kilometer aller Ausleihen des Fahrrads.
| VeloPunkt GmbH – Werkstatt Freiburg im Breisgau |
RECHNUNG Rechnungs-Nr.: W-2026-0815 Rechnungsdatum: 18.09.2026 |
| Kunde | Kunden-Nr. 3307 · Frau Julia Hartmann · Wiesenweg 4 · 79117 Freiburg · Tel. 0761 28349911 |
|---|---|
| Fahrrad | Hersteller: Stadtrad · Modell: Avanti E8 · Rahmennummer: STR-19-77812 |
| Bearbeitet von | Mechaniker-Nr. 7 · Erik Petersen |
| Pos. | Art.-Nr. | Bezeichnung | Menge | Einheit | Einzelpreis | Gesamt |
|---|---|---|---|---|---|---|
| 1 | L-100 | Arbeitszeit Werkstatt | 1,5 | Std. | 64,00 € | 96,00 € |
| 2 | E-2201 | Bremsbelag Scheibenbremse | 2 | Stück | 18,90 € | 37,80 € |
| 3 | E-3105 | Kette 11-fach | 1 | Stück | 29,90 € | 29,90 € |
| 4 | E-4410 | Schlauch 28 Zoll | 2 | Stück | 7,50 € | 15,00 € |
| Nettobetrag | 178,70 € | |||||
| zzgl. 19 % Umsatzsteuer | 33,95 € | |||||
| Rechnungsbetrag | 212,65 € | |||||
Zahlungsart: EC-Karte
Informationen aus dem Gespräch mit der Werkstattleitung:
| Datum | PersNr | Mitarbeiter | Telefon | StationNr | Station | Ort | Schicht | Stunden |
|---|---|---|---|---|---|---|---|---|
| 01.09.2026 | 12 | Weber, Tom | 0761 445-12 | 1 | Hauptbahnhof | Freiburg | Früh | 6,0 |
| 01.09.2026 | 15 | Sanchez, Ana | 0761 445-15 | 2 | Messe | Freiburg | Früh | 6,0 |
| 01.09.2026 | 17 | Yilmaz, Can | 0761 445-17 | 1 | Hauptbahnhof | Freiburg | Spät | 7,5 |
| 02.09.2026 | 12 | Weber, Tom | 0761 445-12 | 3 | Titisee | Titisee-Neustadt | Früh | 6,0 |
| 02.09.2026 | 15 | Sanchez, Ana | 0761 445-15 | 1 | Hauptbahnhof | Freiburg | Spät | 7,5 |
| 02.09.2026 | 21 | Frey, Lisa | 0761 445-21 | 4 | Kaiserstuhl | Vogtsburg | Früh | 6,0 |
| 03.09.2026 | 17 | Yilmaz, Can | 0761 445-17 | 2 | Messe | Freiburg | Früh | 6,0 |
| 03.09.2026 | 12 | Weber, Tom | 0761 445-12 | 1 | Hauptbahnhof | Freiburg | Spät | 7,5 |
Ein Mitarbeiter arbeitet pro Tag höchstens eine Schicht. Eine Frühschicht dauert immer 6,0 Stunden, eine Spätschicht immer 7,5 Stunden.
| Datum | Rad | Mechaniker | Arbeiten | Kosten |
|---|---|---|---|---|
| 03.02.2025 | 101 | Weber | Inspektion | 89,00 € |
| 4.2. | Urban C5 blau | T. Weber | Bremsen vorne + hinten | 145,5 |
| 2025-02-07 | WAW-23-0018 | Weber, Sanchez | Insp. + Reifen | ca. 130 |
| 11.02.25 | 105 | Akku geprüft | inkl. | |
| 11.02.25 | 105 | Akku geprüft | inkl. | |
| Feb 25 | 103/104 | Sanchez | Inspektion | 2x 89 € |
| 14.13.2025 | Tour T7 | A. Sanchez | Kette gewechselt | 29.90 EUR |
| Nr | Name | Adresse | Telefon | Kunde seit | Bemerkung | |
|---|---|---|---|---|---|---|
| 1 | Hoffmann, Lena | Kartäuserstr. 12, 79098 Freiburg | 0761/1234567 | lena.hoffmann@mail.de | 04/2024 | |
| 2 | Jonas Albrecht | Habsburgerstraße 3 79102 Freiburg | +49 761 7654321 | j.albrecht@web,de | 2024 | Stammkunde |
| 3 | Schulze Mira | Denzlingen | – | 2.8.24 | Tel. folgt | |
| 4 | Wagner, Paul | Seestr. 5, Titisee-Neustadt | 07651-4711; 0170 5551234 | paul.wagner@gmx.de | 10.08.2024 | |
| 5 | Hoffmann, L. | Kartäuserstraße 12, Freiburg | 0761 1234567 | lena.hoffmann@mail.de | 18.04.2024 | doppelt? |
| 6 | Keller, Sofia | Wiehre, Freiburg | s.keller(at)posteo.de | Mai 25 | ||
| 7 | Brandt Tim | 77933 Lahr | 07821/99880 | Firma? |
Die Daten sollen in die Tabelle Kunde (Anlage 2) übernommen werden.
Document Databases at a Glance
A document database stores data as self-describing documents, usually in JSON or a binary variant of it. Related documents are grouped in collections. Unlike the rows of a table in a relational database, the documents in one collection do not have to share the same structure: a new field can be added to some documents without changing a schema or migrating existing data.
Data that is read together is often stored together. Instead of splitting an order into several tables and joining them at query time, the order lines can be embedded directly in the order document. This makes typical read operations fast and simple. On the other hand, embedded data may be duplicated in many documents, and changing it later means updating every copy.
Document databases are designed to scale horizontally: a large collection can be distributed across many servers (sharding). Many products guarantee atomic writes only for a single document; transactions that span several documents are either not available or noticeably slower. For data with many relationships and strict consistency requirements, such as accounting, a relational database is often the better choice.
Alle Aufgaben beziehen sich auf die Ausgangssituation in Anlage 1. SQL-Anweisungen in Standard-SQL/MySQL wie im Belegsatz. Gehen Sie – wenn nichts anderes angegeben ist – immer vom Datenbestand in den Anlagen 2 und 3 aus (Aufgaben bauen nicht aufeinander auf).
Für den VeloManager werden Sachverhalte aus dem Fachkonzept modelliert.
| Nr. | Sachverhalt | Kardinalität | Begründung |
|---|---|---|---|
| 1 | Fahrrad – Station: Jedes Fahrrad ist genau einer Heimatstation zugeordnet; an einer Station sind mehrere Fahrräder stationiert. | ||
| 2 | Station – Mitarbeiter (Stationsleitung): Jede Station wird von genau einem Mitarbeiter geleitet; ein Mitarbeiter leitet höchstens eine Station. | ||
| 3 | Ausleihe – Zubehör: Zu einer Ausleihe können mehrere Zubehörteile (Helm, Schloss, Kindersitz) gebucht werden; jedes Zubehörteil wird bei vielen Ausleihen gebucht. |
Geben Sie das zugehörige Relationenmodell in Textnotation an (Primärschlüssel unterstrichen, Fremdschlüssel mit ↑) und begründen Sie, in welche Tabelle der Fremdschlüssel aufgenommen wird.
Angelehnt an: W21 Teil 1, Aufgabe 2b; W23 Teil 1, Aufgabe 4a (Kardinalitäten)
VeloPunkt bietet künftig geführte E-Bike-Touren an. Aus einem Gespräch mit der Tourenleitung liegen folgende Informationen vor:
Angelehnt an: W21 Teil 1, Aufgabe 2b (rekursive Beziehung, m:n); W23 Teil 1, Aufgabe 4a (m:n mit Attributen)
Die Online-Buchung des VeloManagers soll um Zubehör (z. B. Helm, Kindersitz, Packtasche) erweitert werden. Für die Datenhaltung liegt folgendes ER-Modell vor:
Informationen aus der Ist-Analyse:
Angelehnt an: S26 Teil 2, Aufgabe 3a (ER-Modell überführen und erweitern)
| Nr. | Aussage | verletzte NF |
|---|---|---|
| 1 | In einer Kundentabelle stehen bei manchen Kunden zwei Telefonnummern im Feld „Telefon“, getrennt durch ein Semikolon. | |
| 2 | Tabelle AusleiheKunde(AusleiheNr, Beginn, KundenNr, Nachname): Nachname hängt von KundenNr ab. | |
| 3 | Tabelle Zubehoerbuchung(AusleiheNr, ZubehoerNr, Anzahl, Bezeichnung): Bezeichnung hängt nur von ZubehoerNr ab. |
Der Schichtplan der Stationen (Anlage 5) wird bisher als Excel-Liste geführt und soll in den VeloManager übernommen werden.
Angelehnt an: W25 Teil 1, Aufgabe 4a/4b; S23 Teil 1, Aufgabe 4ca
Die Werkstatt soll ihre Rechnungen künftig im VeloManager erstellen. Grundlage sind das bisherige Rechnungsformular und die Informationen der Werkstattleitung in Anlage 4.
Angelehnt an: W21 Teil 2, Aufgabe 3; S22 Teil 2, Aufgabe 3; W25 Teil 1, Aufgabe 4c (Datenmodell in 3NF aus Beleg bzw. Beispieldaten)
Erstellen Sie jeweils eine SQL-Anweisung für die folgenden Auswertungen (Anlage 2).
Angelehnt an: W22 Teil 2, Aufgabe 4c (LIKE-Muster PLZ); S23 Teil 2, Aufgabe 4a (YEAR, IS NULL)
Angelehnt an: W21 Teil 2, Aufgabe 4e (Join über mehrere Tabellen); S22 Teil 2, Aufgabe 4bc (LEFT JOIN)
Die Geschäftsführung möchte die abgerechneten Mietbeträge kontrollieren und einen Überblick über die Kundenaktivität im Jahr 2026 erhalten.
Angelehnt an: W24 Teil 2, Aufgabe 4c (Datumsdifferenz); W22 Teil 2, Aufgabe 4a und S26 Teil 2, Aufgabe 4b (LEFT JOIN)
SELECT COUNT(*), COUNT(Kosten) FROM Wartung; an und begründen Sie den Unterschied.Angelehnt an: W25 Teil 2, Aufgabe 4c (HAVING) und 4e (SUM je Kategorie)
Für die Planung der Flotte und der Werkstatt werden Auswertungen benötigt.
SELECT k.KundenNr, k.Nachname, COUNT(a.AusleiheNr) AS Anzahl FROM Kunde k LEFT JOIN Ausleihe a ON k.KundenNr = a.KundenNr WHERE COUNT(a.AusleiheNr) = 0 GROUP BY k.KundenNr;
Nennen Sie zwei Fehler und geben Sie die korrigierte Abfrage an. Erläutern Sie außerdem, welches Ergebnis entstünde, wenn in der korrigierten Abfrage COUNT(*) statt COUNT(a.AusleiheNr) verwendet würde.
Angelehnt an: S22 Teil 2, Aufgabe 4bc (LEFT JOIN mit COUNT); W21 Teil 2, Aufgabe 4d (HAVING)
DELETE FROM Kunde WHERE KundenNr = 1004; wird vom Datenbanksystem abgewiesen. Erläutern Sie den Grund und nennen Sie eine Möglichkeit, den Kunden dennoch zu löschen.Angelehnt an: W25 Teil 2, Aufgabe 4a; S24 Teil 2, Aufgabe 4a
Angelehnt an: W21 Teil 2, Aufgabe 4c (UPDATE mit Unterabfrage); W23 Teil 2, Aufgabe 4c (UPDATE mit JOIN)
Die Tabelle Ausleihe soll regelmäßig bereinigt werden. Gehen Sie bei allen Teilaufgaben vom Datenbestand der Anlagen 2 und 3 aus.
Angelehnt an: W22 Teil 2, Aufgabe 4b; S24 Teil 2, Aufgabe 4c; S26 Teil 2, Aufgabe 4ca/4cb (Archivierung)
Angelehnt an: W23 Teil 1, Aufgabe 3a (ACID); S22 Teil 2, Aufgabe 4ac (Index)
Bei der Rückgabe eines Fahrrads führt der VeloManager drei Schritte aus: (1) In der Ausleihe werden Ende, Kilometer und Betrag eingetragen. (2) Eine Rechnung wird erzeugt. (3) Hat das Fahrrad seit der letzten Wartung mehr als 1.000 km zurückgelegt, wird automatisch ein Wartungsauftrag angelegt.
Für eine geplante Smartphone-App wird überlegt, Kundendaten und Ausleihen zusätzlich in einer dokumentenorientierten Datenbank bereitzustellen.
| Relationale Datenbank | Dokumentenorientierte Datenbank |
|---|---|
| Tabelle | |
| Datensatz (Zeile) | |
| Spalte (Attribut) |
Angelehnt an: W23 Teil 1, Aufgabe 3b/3c (Begriffe, JSON, Einbettung); S22 Teil 1, Aufgabe 2c (NoSQL aus englischem Text)
Angelehnt an: W23 Teil 2, Aufgabe 4d (Vergleich mit AVG); S22 Teil 2, Aufgabe 4bb (Unterabfrage mit IN)
Angelehnt an: W23 Teil 2, Aufgabe 4d (korrelierte Unterabfrage); S22 Teil 2, Aufgabe 4bb (DELETE mit NOT EXISTS)
| DDL | DML | DCL |
|---|---|---|
| Spalte | Datentyp |
|---|---|
| Kunde.PLZ | |
| Fahrrad.Kaufpreis | |
| Ausleihe.Beginn |
Angelehnt an: S26 Teil 2, Aufgabe 4a; W22 Teil 2, Aufgabe 3c
Angelehnt an: W21 Teil 2, Aufgabe 4a (CREATE TABLE); S22 Teil 2, Aufgabe 4ba (CREATE INDEX)
Die Datenbank soll erweitert werden. Erstellen Sie jeweils die SQL-Anweisung(en).
Angelehnt an: W25 Teil 2, Aufgabe 4d (ALTER TABLE ADD/DROP und UPDATE mit SUBSTRING)
SELECT KundenNr FROM Ausleihe UNION SELECT KundenNr FROM Ausleihe_Archiv; liefert und wie viele es mit UNION ALL wären. Begründen Sie den Unterschied.Für den Jahresbericht wird eine Statistik über alle Ausleihen benötigt – aktuelle und archivierte (Anlagen 2 und 3).
SELECT YEAR(Beginn) AS Jahr, COUNT(*), SUM(Betrag), SUM(Kilometer) FROM Ausleihe GROUP BY YEAR(Beginn) UNION ALL SELECT YEAR(Beginn), COUNT(*), SUM(Betrag), SUM(Kilometer) FROM Ausleihe_Archiv GROUP BY YEAR(Beginn) ORDER BY Jahr;
Erläutern Sie, warum diese Abfrage die Anforderung aus a) mit den vorliegenden Daten nicht erfüllt.
Angelehnt an: S24 Teil 2, Aufgabe 4d (UNION ALL mit GROUP BY YEAR)
Die Werkstatt erhält einen eigenen Zugang zur Datenbank velomanager. Erstellen Sie die SQL-Anweisungen.
Angelehnt an: S23 Teil 2, Aufgabe 4d (CREATE USER, GRANT SELECT)
Im VeloManager arbeiten verschiedene Personengruppen. Folgende Anforderungen wurden aufgenommen:
| Rolle | Kunde | Fahrrad | Ausleihe | Wartung |
|---|---|---|---|---|
| Stationspersonal | ||||
| Werkstatt | ||||
| Controlling |
Angelehnt an: S22 Teil 2, Aufgabe 4aa/4ab
v_laufende_ausleihen, die für alle noch nicht beendeten Ausleihen die AusleiheNr, den Beginn, den Nachnamen des Kunden, das Modell und den Namen der Heimatstation des Fahrrads (Spaltenname „Station“) enthält. Geben Sie außerdem an, welche Zeile(n) die View mit den Daten aus Anlage 2 liefert.| Tabelle | Ereignis | Zeitpunkt (BEFORE/AFTER) |
|---|---|---|
| Bedingung | Aktion | |
CREATE PROCEDURE rueckgabe(IN p_nr INT, IN p_km INT)
BEGIN
UPDATE Ausleihe a
INNER JOIN Fahrrad f ON f.FahrradNr = a.FahrradNr
INNER JOIN Kategorie k ON k.KategorieNr = f.KategorieNr
SET a.Ende = CURDATE(),
a.Kilometer = p_km,
a.Betrag = (DATEDIFF(CURDATE(), a.Beginn) + 1) * k.Tagespreis
WHERE a.AusleiheNr = p_nr
AND a.Ende IS NULL;
END
Beschreiben Sie, was die Prozedur bewirkt. Geben Sie den Aufruf für die Rückgabe der laufenden Ausleihe 5012 mit 84 gefahrenen Kilometern an und berechnen Sie den Betrag, der bei einer Rückgabe am heutigen Tag (10.10.2026) gespeichert wird.
Angelehnt an: S22 Teil 2, Aufgabe 4a (Trigger, Stored Procedure)
Die Werkstatt möchte die Einträge ihres bisherigen Werkstattbuchs (Anlage 6) in die Tabelle Wartung (Anlage 2) importieren.
Angelehnt an: W24 Teil 2, Aufgabe 3ba
Die Kundenkartei (Anlage 7) soll in die Tabelle Kunde (Anlage 2) übernommen werden.
| Spalte | Problem | Transformation |
|---|---|---|
| Name | ||
| Adresse | ||
Angelehnt an: W24 Teil 2, Aufgabe 3bb/3bc
Alle Dateien liegen im Ordner Prüfungsvorbereitung. Lösungen gibt es nur für 2023 Sommer, 2023 Winter, 2024 Sommer und 2025 Winter. Den originalen SQL-Syntax-Auszug findest du in den Belegsätzen von W21, S22, W22, S24 und W25 (z. B. 2024/sommer/AE Sommer 2024 Belegsatz.pdf).
| Prüfung | Aufgaben (Block Datenbanken) | Datei | Lösung |
|---|---|---|---|
| Winter 2021/22 | T1 A2b: ER-Modell (rekursiv, m:n), 16 P · T2 A3: Relationenmodell 3NF, 25 P · T2 A4: CREATE TABLE, SELECT, UPDATE mit Unterabfrage, GROUP BY/HAVING, Join über 4 Tabellen, 25 P | 2021/winter/AE 2021 Winter Teil 1.pdf, … Teil 2.pdf | – |
| Sommer 2022 | T1 A2c: NoSQL aus engl. Text, 9 P · T2 A3: 3NF aus Tarifübersicht, 20 P · T2 A4: Stored Procedure, Trigger, Index, CREATE INDEX, DELETE mit NOT IN, LEFT JOIN + COUNT, 30 P | 2022/sommer/AE 2022 Sommer Teil 1.pdf, … Teil 2.pdf | – |
| Winter 2022/23 | T1 A4c: NoSQL vs. relational, 5 P · T2 A3: ER-Modell erweitern, 3NF, Datentypen, 25 P · T2 A4: LEFT JOIN + GROUP BY, INSERT…SELECT + DELETE (Archiv), LIKE, 25 P | 2022/winter/AE 2022 Winter Teil 1.pdf, … Teil 2.pdf | – |
| Sommer 2023 | T1 A4c: Änderungsanomalie, Relationenmodell 3NF mit JSON-Daten, 16 P · T2 A4: COUNT/YEAR/IS NULL, 3-Tabellen-Join, LEFT JOIN + COUNT, CREATE USER/GRANT, 25 P | 2023/sommer/AE Sommer 2023 Teil 1.pdf, … Teil 2.pdf | 2023/sommer/AE Sommer 2023 Teil 1+2 Lösungen.pdf |
| Winter 2023/24 | T1 A3: ACID, Dokument-DB, JSON, 25 P · T1 A4a: ER-Diagramm m:n mit Attributen, 14 P · T2 A3a: Relationenmodell 3NF, 18 P · T2 A4: BETWEEN, GROUP BY, UPDATE mit JOIN, korrelierte Unterabfrage, 25 P | 2023/winter/AE Winter 2023 Teil 1.pdf, … Teil 2.pdf | 2023/winter/AE Winter 2023 Teil 1 Lösungen.pdf, … Teil 2 Lösungen.pdf |
| Sommer 2024 | T1 A4a: ER-Modell erweitern (Soft Delete, m:n), 10 P · T2 A4: DELETE, MIN/MAX/AVG/COUNT je Gruppe, Archiv INSERT…SELECT + DELETE, UNION ALL + GROUP BY YEAR, 30 P | 2024/sommer/AE Sommer 2024 Teil 1+2+3.pdf | 2024/sommer/AE Sommer 2024 Teil 1 Lösungen.pdf, … Teil 2 Lösungen.pdf |
| Winter 2024/25 | T2 A3a: Relationenmodell 3NF (m:n), 16 P · T2 A3b: Datenqualität beim Import, 13 P · T2 A4: SELECT/JOIN, Datumsdifferenz, 21 P | 2024/winter/AE Winter 2024 Teil 2.pdf | – |
| Winter 2025/26 | T1 A4: Redundanz, Anomalien, Tabelle in 3NF, 24 P · T2 A4: INSERT, SUM über 4 Tabellen, HAVING, ALTER TABLE + UPDATE mit SUBSTRING, SUM je Kategorie, 25 P | 2025/winter/AE Winter 2025 Teil 1.pdf, … Teil 2.pdf | 2025/winter/AE Winter 2025 Lösungserleuterungen.pdf |
| Sommer 2026 | T2 A3a: ER-Modell → Relationenmodell 3NF erweitern, 20 P · T2 A4: CRUD → DDL/DML, LEFT JOIN + GROUP BY (MAX/AVG), Archiv INSERT…SELECT, DELETE-Reihenfolge (FK), 25 P | 2026/sommer/AE Sommer 2026 Teil 2.pdf | – |