Zum Inhalt
wannacode

Die Bäckerei, Etappe 5: die Datenbank arbeitet von selbst

Kurz gesagt: Etappe 5 fügt einen Index, eine View mit den Bestellsummen, einen Trigger, der den Lagerbestand senkt, und eine neue Spalte mit ALTER TABLE hinzu.

Problem

Die Dinge, an die man denken muss

In Etappe 4 wurde der Lagerbestand mit einer von Hand geschriebenen Abfrage gesenkt, und die Summe einer Bestellung wurde jedes Mal mit drei Tabellen berechnet. Die Bäckerei wächst: Aus den Bestellungen werden Tausende, und mehr Leute schreiben Abfragen. Dinge, die davon abhängen, dass jemand daran denkt, werden früher oder später vergessen.

Diese Etappe gibt die Arbeit an die Datenbank ab: ein Index für die schnelle Suche, eine View für die Summen, ein Trigger fürs Lager und eine neue Spalte für das Telefon.

Die Idee

Wie die Datenbank sucht

Die Seite „Meine Bestellungen“ fragt nach den Bestellungen eines Kunden. EXPLAIN QUERY PLAN zeigt, wie die Datenbank das erledigt:

SQLleere Datenbank

SCAN orders: Die Datenbank liest jede Bestellung und schaut auf den Kunden. Bei sechs Bestellungen spielt das keine Rolle, bei einer Million ist es langsam.

Probier es aus

Der Index

Lege einen Index orders_customer auf die Spalte customer_id von orders an.

SQLleere Datenbank

Dieselbe Abfrage mit dem Index:

SQLleere Datenbank

SEARCH … USING INDEX: Die Datenbank geht direkt zu den Bestellungen von Kunde 2.

Genauer, für Neugierige

SQLite legt für einen Fremdschlüssel nicht von selbst einen Index an, PostgreSQL auch nicht. Eine Spalte, die auf eine andere Tabelle zeigt, will fast immer einen Index: Nach ihr werden Tabellen verbunden und durchsucht. Der Index ist aber nicht gratis: Jedes INSERT und UPDATE aktualisiert ihn.

Probier es aus

Die View

Die Summe einer Bestellung sind jedes Mal drei Tabellen und ein GROUP BY. Eine View ist eine Abfrage mit einem Namen: Du liest aus ihr wie aus einer Tabelle.

Lege eine View order_totals an, mit der Nummer der Bestellung (id), dem Kunden (customer_id), dem Status und der Summe (total, auf 2 Stellen gerundet) jeder Bestellung.

SQLleere Datenbank

Sieh es dir an

Die View als Tabelle

Wie viel jeder Kunde ausgegeben hat, ohne die stornierten Bestellungen. Die Summe über die drei Tabellen steckt in der View:

SQLleere Datenbank

Die View speichert keine Daten, sie speichert ihre Abfrage. Eine neue Bestellung erscheint sofort darin:

SQLleere Datenbank

Probier es aus

Der Trigger

Ein Trigger ist Code, den die Datenbank bei einem INSERT, UPDATE oder DELETE in einer Tabelle von selbst ausführt. In seinem Rumpf ist new die neue Zeile.

Lege einen Trigger take_stock an: Nach jeder neuen Zeile in order_items sinkt der Lagerbestand des Produkts in der Zeile um deren Stückzahl.

SQLleere Datenbank

Sieh es dir an

Der Trigger und die Regeln

Mit dem Trigger bestellt Kalin 20 Kozunaks, und es gibt 10:

SQLleere Datenbank

Das UPDATE im Trigger verletzt CHECK (stock >= 0). Der Trigger ist Teil des INSERT, also kommt auch die Zeile der Bestellung nicht hinein: Die Datenbank hat keine Zeile, die „20 Kozunaks verkauft“ sagt, wenn es sie nicht gibt.

Genauer, für Neugierige

Trigger halten eine Regel an einer einzigen Stelle, aber sie sind versteckt: Wer den Code des Programms liest, sieht sie nicht. Darum setzt man sie sparsam ein, für Dinge, die immer passieren müssen, egal, was in die Datenbank schreibt. Der Lagerbestand hier ist so etwas, das Senden einer E-Mail nicht.

Probier es aus

Eine neue Spalte

Die Bäckerei will die Kunden anrufen, wenn die Bestellung fertig ist. Die Tabelle hat Daten, also wird sie nicht neu angelegt: ALTER TABLE fügt ihr eine Spalte hinzu.

Füge customers eine Spalte phone vom Typ TEXT hinzu, die fehlen darf.

SQLleere Datenbank

Mit NOT NULL geht es nicht:

SQLleere Datenbank
Genauer, für Neugierige

ALTER TABLE kann in SQLite Spalten hinzufügen, umbenennen und (seit 3.35) löschen. Eine Regel wie CHECK oder einen Fremdschlüssel zu einer vorhandenen Spalte hinzufügen kann es nicht: Dann wird die Tabelle neu angelegt (eine neue Tabelle, INSERT … SELECT, DROP der alten und eine Umbenennung). In PostgreSQL macht ALTER TABLE … ADD CONSTRAINT das direkt.

Die Idee

Was als Nächstes kommt

Die Datenbank ist voll, schnell und hält ihre Regeln von selbst ein. Die letzte Etappe ist das Ende: ein Bericht, eine Kopie der Datenbank und DROP von allem in der richtigen Reihenfolge.

Test

Teste dich

1. Speichert die View order_totals die Summen der Bestellungen?
2. Der Trigger senkt den Lagerbestand, und das Produkt geht aus. Was passiert mit der Zeile in order_items?
3. Warum gibt ALTER TABLE customers ADD COLUMN phone TEXT NOT NULL einen Fehler?

Erstellt von Ivo Gergov im Rahmen der Kampagne von Evo Tech für zugängliche Programmierausbildung ·