Transaktionen
Manche Änderungen gehören zusammen. Eine neue Bestellung ist eine Zeile in bestellungen und eine Zeile in positionen für jedes ihrer Spiele. Was ist, wenn die Bestellung hineinkommt und dann etwas schiefgeht, bevor ihre Positionen es tun? Die ID eines Spiels ist falsch, die App stürzt ab, der Server verliert den Strom. Der Shop hat dann eine Bestellung ohne Inhalt. Solche Änderungen müssen ganz oder gar nicht geschehen.
Dafür gibt es eine Transaktion. BEGIN startet sie, und die Änderungen danach gehören zu ihr. COMMIT beendet sie und speichert alle ihre Änderungen auf einmal. Die Bestellung von Goal Rush durch Max Krause, sicher aufgegeben:
BEGIN;
INSERT INTO bestellungen (kunde_id, bestellt_am, status)
VALUES (14, '2026-01-08', 'bezahlt');
INSERT INTO positionen (bestellung_id, spiel_id, menge, preis)
VALUES (31, 8, 1, 50);
COMMIT;Bis zum COMMIT sieht niemand sonst die Änderungen: Andere Benutzer der Datenbank sehen den Shop so, wie er vor BEGIN war. Danach sehen sie alle Änderungen auf einmal, nie nur die Hälfte davon. Und wenn mittendrin etwas schiefgeht, beendet die App die Transaktion stattdessen mit ROLLBACK, das jede Änderung seit BEGIN rückgängig macht, als wäre sie nie geschehen. Die halb fertige Bestellung verschwindet.
Innerhalb einer Transaktion siehst du deine eigenen Änderungen, du kannst also auch etwas ausprobieren, das Ergebnis ansehen und es zurücknehmen:
BEGIN;
DELETE FROM bewertungen;
SELECT COUNT(*) AS bewertungen
FROM bewertungen;
ROLLBACK;
SELECT COUNT(*) AS bewertungen
FROM bewertungen;| bewertungen |
|---|
| 0 |
| bewertungen |
|---|
| 25 |
Die erste Abfrage findet keine Bewertungen, die zweite wieder alle 25: ROLLBACK hat sie zurückgebracht.
Ohne BEGIN ist jede Anweisung eine kleine Transaktion für sich. Deshalb ändert ein UPDATE, das mittendrin fehlschlägt, nichts, wie du bei den Preisen gesehen hast. Eine Transaktion tut dasselbe für mehrere Anweisungen zusammen. (In anderen Datenbanken siehst du statt BEGIN vielleicht auch START TRANSACTION.)
In diesem Kurs beginnt jedes Ausführen mit einer frischen Datenbank, du siehst also den Unterschied nicht, den COMMIT macht, aber in einer echten Datenbank sorgt er dafür, dass die Änderungen bleiben. Typischer Fehler: COMMIT vergessen. Deine eigenen Abfragen sehen die Änderungen, also wirkt alles in Ordnung, aber wenn die App die Verbindung trennt, macht die Datenbank die unfertige Transaktion rückgängig, und die Änderungen sind verloren. Hier merkst du es beim nächsten BEGIN: Eine Transaktion kann nicht innerhalb einer anderen beginnen, also endet es mit cannot start a transaction within a transaction. Und auch ein COMMIT ohne BEGIN ist ein Fehler: cannot commit - no transaction is active.
So schreibst du es:
Anweisungen
- 1
Hannes Schulz (Kunde 12) gibt am 15.01.2026 seine erste Bestellung auf: ein Exemplar von Star Pilots (Spiel 7) und eines von Cube Logic (Spiel 6), jeweils zu seinem Preis in
spiele. Füge in einer Transaktion die Bestellung mit dem Statusbezahlt(ihre ID kommt automatisch und wird 31 sein) und ihre zwei Positionen hinzu und schließe die Transaktion mitCOMMITab. - 2
Zeige darunter, was in Bestellung 31 steht: den Titel jedes Spiels, die Menge und den Preis, sortiert nach dem Titel:
titel menge preis Cube Logic 1 5 Star Pilots 1 35 - 3
Hannes möchte auch Robot Rebellion bestellen. Beginne eine neue Transaktion, füge seine zweite Bestellung hinzu (vom 16.01.2026, Status
bezahlt) und zeige die ID und das Datum aller Bestellungen von Hannes, sortiert nach der ID. Aber Robot Rebellion ist noch nicht erschienen, also kann der Shop es nicht verkaufen: Mache die Transaktion mitROLLBACKrückgängig und zeige seine Bestellungen noch einmal mit derselben Abfrage. Die beiden Ergebnisse sollten so aussehen:id bestellt_am 31 2026-01-15 32 2026-01-16 id bestellt_am 31 2026-01-15