Datenbanken und Datendienste — das Zusammenspiel zwischen Frontend und Daten
Tabellen, Schlüssel, SQL und wie eine Weblösung sicher mit ihren Daten spricht
Einleitung
Eine Webseite, die sich nichts merkt, ist in der Praxis nicht viel wert — ein Webshop muss sich Bestellungen merken, ein Forum muss sich Beiträge merken, und ein Login muss sich merken, wer du bist. Das ist die Aufgabe der Datenbank. Die Verordnung für die Webentwickler-Ausbildung benennt dies direkt als eigenständiges Fachgebiet: der Auszubildende muss das Zusammenspiel zwischen Datenbankstruktur und Frontend darlegen und relevante Datendienste zur Entwicklung von Weblösungen einsetzen können.
Die relationale Datenbank — Tabellen, Zeilen und Schlüssel
Der verbreitetste Datenbanktyp im Web ist die relationale Datenbank. Die Daten liegen in Tabellen, wobei jede Zeile ein Datensatz und jede Spalte ein bestimmtes Feld ist — eine Tabelle mit Benutzern hat zum Beispiel Spalten für Name, E-Mail und Anlagedatum. Jede Zeile hat einen Primärschlüssel, eine eindeutige ID, die genau auf diesen einen Datensatz zeigt. Zusammenhänge zwischen Tabellen werden mit Fremdschlüsseln hergestellt: Eine Bestelltabelle speichert nicht noch einmal Name und Adresse des Kunden, sondern nur dessen ID, die zurück auf die Kundentabelle zeigt. Das ist der Grundgedanke des Relationalen — die Daten sind aufgeteilt, aber über Schlüssel miteinander verbunden.
SQL und CRUD — die vier Grundaktionen
SQL (Structured Query Language) ist die Sprache, mit der man eine relationale Datenbank abfragt. Egal, welches Programm oder Framework dazwischenliegt, es läuft fast immer auf dieselben vier grundlegenden Aktionen hinaus, oft CRUD genannt.
- 01Create — lege einen neuen Datensatz an (SQL: INSERT)
- 02Read — einen oder mehrere Datensätze abrufen (SQL: SELECT)
- 03Update — einen vorhandenen Datensatz ändern (SQL: UPDATE)
- 04Delete — einen Datensatz entfernen (SQL: DELETE)
Normalisierung — vermeiden, dasselbe mehrfach zu speichern
Normalisierung ist die Arbeit, die Tabellen so zu strukturieren, dass dieselbe Information nicht unnötig mehrfach gespeichert wird. Speichert man die Adresse eines Kunden bei jeder einzelnen Bestellung, müssen alle Bestellungen geändert werden, wenn der Kunde umzieht — und macht man das nicht konsequent, entstehen widersprüchliche Daten. Speichert man die Adresse stattdessen an einer Stelle und lässt die Bestellungen über einen Fremdschlüssel darauf verweisen, existiert die Wahrheit nur an einem Ort. Das gemeinsame Abrufen der Daten kostet etwas mehr (man muss die Tabellen 'joinen'), gewinnt aber deutlich an Konsistenz und Wartbarkeit.
Relational oder NoSQL — wähle nach den Daten, nicht nach der Mode
Nicht alle Daten passen gleich gut in feste Tabellen mit Spalten. NoSQL-Datenbanken (Dokument-, Schlüssel/Wert- und Graphdatenbanken sind die häufigsten Typen) speichern Daten flexibler, oft als Dokumente ohne feste Vorlage für jedes Feld. Sie eignen sich gut für Daten, die in ihrer Form stark variieren, oder wenn auf sehr große Schreibmengen skaliert werden muss. Relationale Datenbanken gewinnen dagegen, wenn die Daten klare Zusammenhänge haben und man Garantien dafür braucht, dass eine Aktion entweder ganz oder gar nicht ausgeführt wird (Transaktionen).
| Eigenschaft | Relationale Datenbank | NoSQL (z. B. Dokumentendatenbank) |
|---|---|---|
| Struktur | Feste Tabellen mit Spalten | Flexible Dokumente, wechselnde Felder |
| Zusammenhänge | Fremdschlüssel und Joins | Oft Daten in einem Dokument gesammelt |
| Am besten für | Daten mit klaren Beziehungen und Anforderungen an Konsistenz | Daten, die in ihrer Form variieren, oder sehr hohe Schreibgeschwindigkeit |
| Sprache | SQL | Von System zu System unterschiedlich |
Das ORM — die Brücke zwischen Code und Datenbank
Statt überall im Backend-Code rohe SQL-Abfragen zu schreiben, nutzen viele einen ORM (Object-Relational Mapper). Er lässt dich mit den Tabellen der Datenbank wie mit gewöhnlichen Objekten deiner Programmiersprache arbeiten und übersetzt das im Hintergrund in SQL. Das macht den Code lesbarer und weniger fehleranfällig — aber es bleibt wichtig zu verstehen, was der ORM tatsächlich an die Datenbank schickt, nicht zuletzt dann, wenn eine Abfrage langsam wird, weil sie weit mehr Daten holt, als die Seite wirklich braucht.
Der Datendienst muss abgesichert und nicht nur gebaut werden
Ein Datendienst ist die Schicht, die dem Frontend Daten bereitstellt — typischerweise eine API, die HTTP spricht, wie im Artikel über Web-APIs beschrieben. Der Zugang zu den Daten muss genauso kontrolliert werden wie der Rest des Backends: Nur authentifizierte und autorisierte Aufrufe dürfen Daten lesen oder ändern, die Verbindung zur Datenbank muss durch ein Login geschützt sein, das niemals im Frontend-Code liegt, und sensible Daten sollten nur weitergegeben werden, wenn es für die Aufgabe wirklich notwendig ist.
“Eine Datenbank ist nicht einfach ein Ort, an dem Daten liegen und warten — sie ist eine Struktur, die dir entweder hilft oder dich daran hindert, deinen eigenen Daten zu vertrauen.”
— Gängige Faustregel im Datenbankdesign