Abschnitt 16 · Lektion 1
Warum eine Datenbank
In Mias Laden pflegen zwei Programme dieselbe bestand.csv, und am Ende des Tages fehlt ein
Verkauf. Die Daten in diesem Kurs liegen bisher in Dateien. Das Haushaltsbuch steht in
ausgaben.txt, die Mitglieder eines Vereins in einer CSV, die Einstellungen in JSON. Das passt,
solange ein Programm die Datei liest, etwas damit macht und sie danach ganz schreibt. Wo das nicht
mehr reicht, kommt eine Datenbank.
Für die Sprache SQL selbst steht auf der Plattform ein eigener Kurs im Fahrplan. Hier geht es darum, wie Python mit einer Datenbank redet.
Wer zuletzt schreibt, gewinnt
from pathlib import Path
datei = Path("bestand.csv")
datei.write_text("Brot;12\nButter;8\nMilch;30\n", encoding="utf-8")
# Zwei Programme lesen den Bestand zur selben Zeit: die Kasse und das Lager.
kasse = datei.read_text(encoding="utf-8")
lager = datei.read_text(encoding="utf-8")
# Die Kasse verkauft drei Stück Butter, das Lager bucht eine Lieferung Milch.
datei.write_text(kasse.replace("Butter;8", "Butter;5"), encoding="utf-8")
datei.write_text(lager.replace("Milch;30", "Milch;54"), encoding="utf-8")
print(datei.read_text(encoding="utf-8"), end="") Die beiden Programme sind die Kasse, die jeden Verkauf abzieht, und das Lager, das jede Lieferung dazuzählt. Beide machen es wie in Lektion 12.5. Datei lesen, ändern, ganz zurückschreiben.
Laufen sie zur selben Zeit, lesen beide denselben Stand. Die Kasse schreibt ihren zurück, mit 5 Stück Butter. Gleich danach schreibt das Lager seinen, und da steht die Butter noch bei 8. Am Ende ist der Verkauf weg. Es gibt keine Fehlermeldung, und keines der beiden Programme hat etwas falsch gemacht.
Wenn du schon mal zu zweit an einer Tabelle gearbeitet hast, die per Mail hin- und herging, kennst du das. Wer zuletzt speichert, gewinnt. Deshalb sperrt Excel eine Datei auf einem Netzlaufwerk, solange jemand sie offen hat.
Zwei Dinge kommen noch dazu, und die fangen nicht erst bei zwei Programmen an. Jede Frage an eine CSV ist eine Schleife über die ganze Datei. Bei einem Haushaltsbuch, das seit Jahren wächst, sind das bei jeder Frage alle Jahre. Und jede Änderung schreibt die ganze Datei neu. Stürzt das Programm dabei ab, liegt danach eine halbe Datei da.
Eine Datei, die man fragt
Mit einer Datenbank (database) fällt diese Arbeit weg. Man liest sie nicht, man fragt sie. Welche Artikel liegen unter fünf Stück? Was ist im September für Lebensmittel draufgegangen? Die Datenbank sucht selbst und gibt nur zurück, was passt.
Wenn zwei Programme zur selben Zeit etwas ändern, ändert jedes nur seine Zeilen, statt die ganze Datei zurückzuschreiben. Geschrieben wird nacheinander, und eine halbe Datei bleibt nie zurück. Eine Lieferung im Lager überschreibt dann keinen Verkauf an der Kasse mehr.
Die meisten Datenbanken sind eigene Programme, die auf einem Server laufen, PostgreSQL oder MySQL zum Beispiel. Mit denen verbindet man sich über das Netz, mit Name und Passwort, und jemand muss sie einrichten und pflegen.
Bei SQLite steckt die ganze Datenbank in einer einzigen Datei. Gelesen und geschrieben wird sie mit
einem Modul, das mit Python kommt, sqlite3. Es gibt nichts zu installieren und nichts
einzurichten, und kopieren lässt sich die Datenbank wie jede andere Datei. SQLite steckt in jedem
Smartphone und in den meisten Browsern, und für ein eigenes Werkzeug reicht es lange.
Tabelle, Zeile, Spalte
import sqlite3
verbindung = sqlite3.connect("laden.db")
verbindung.execute("CREATE TABLE artikel (name TEXT, preis INTEGER, bestand INTEGER)")
verbindung.close()
print("laden.db hat jetzt eine Tabelle artikel") Eine Datenbank besteht aus Tabellen (table), so wie eine Excel-Mappe aus Blättern. Eine Tabelle hat Spalten (column) mit Namen, und jeder Eintrag ist eine Zeile (row), wie eine Zeile in einer CSV. Anders als bei einer CSV legt man die Spalten aber vorher fest, einmal, mit ihrem Namen und der Art von Wert, die hineingehört.
sqlite3.connect("laden.db") öffnet eine Verbindung (connection) zur Datei laden.db. Gibt es die
Datei noch nicht, legt connect sie an. Mit execute (ausführen) geht ein Befehl an die Datenbank.
Dieser Befehl ist nicht in Python geschrieben, sondern in SQL (Structured Query Language), einer
eigenen kleinen Sprache nur für Datenbanken. Python reicht ihn als Text weiter, deshalb steht er in
Anführungszeichen. CREATE TABLE artikel legt eine Tabelle mit dem Namen artikel an. In den
Klammern stehen die Spalten mit ihrer Art, durch Kommas getrennt.
Die Großbuchstaben sind Gewohnheit und keine Pflicht. Man sieht daran, was zu SQL gehört und was ein
selbst gewählter Name ist. Am Ende schließt close() die Verbindung, wie bei einer Datei.
Was in laden.db steht, kannst du dir über die Befehlsleiste ansehen. sqlite3 gibt es nämlich
auch als Programm für das Terminal, und dort nennt .tables die Tabellen und .schema den Befehl,
mit dem sie angelegt wurden. Auf dem Mac ist das Programm schon da, unter Windows und vielen
Linux-Systemen muss man es erst installieren. Mit cat sähe man in laden.db übrigens vor allem
Zeichensalat, denn eine Datenbank ist keine Textdatei.
Welche Art von Wert
SQLite kennt nur wenige Arten von Werten. Für ein Haushaltsbuch reichen drei davon, INTEGER für
ganze Zahlen, REAL für Kommazahlen und TEXT für Text. Zwei Dinge fehlen aber, die in jedem
Haushaltsbuch vorkommen.
Ein Datum gibt es nicht als eigene Art. Es steht als Text in der Tabelle, und zwar in der Form
2026-09-03, mit dem Jahr zuerst. Das ist keine Geschmackssache. Text wird Zeichen für Zeichen
verglichen, und nur wenn das Jahr vorn steht, liegt 2026-09-03 vor 2026-10-01. In der Form
03.09.2026 käme der 1. Oktober vor dem 3. September, die Falle aus Lektion 8.7. Aus einem date
macht isoformat() diese Form: date(2026, 9, 3).isoformat() gibt '2026-09-03'.
Und Geld gibt es nicht als Decimal. REAL ist dieselbe Kommazahl wie float in Python, samt
0.30000000000000004. Beträge stehen deshalb als ganze Zahlen in Cent in der Tabelle, 2,49 Euro
also als 249, so wie schon in Abschnitt 2. Ganze Zahlen rechnen genau, auch beim Zusammenzählen.
In Euro umgerechnet wird erst, wenn der Betrag im Terminal erscheint.
Ein zweiter Start
import sqlite3
def anlegen():
verbindung = sqlite3.connect("laden.db")
verbindung.execute("CREATE TABLE artikel (name TEXT, preis INTEGER, bestand INTEGER)")
verbindung.close()
print("Tabelle angelegt")
anlegen() # heute
anlegen() # morgen, laden.db liegt dann noch da Ein Programm, das eine Datenbank anlegt, läuft selten nur einmal. Im Beispiel wird anlegen()
zweimal aufgerufen, so als würdest du dasselbe Programm heute starten und morgen wieder. Beim ersten
Aufruf wird die Tabelle angelegt. Der zweite trifft auf die Datei vom ersten, in der die Tabelle
schon steht, und endet mit sqlite3.OperationalError: table artikel already exists. Die Tabelle
gibt es also schon.
Dasselbe passiert mit dem Beispiel davor, wenn du es im Terminal mit python main.py noch einmal
startest. Im Terminal räumt niemand auf, laden.db bleibt liegen, genau wie auf deinem eigenen
Rechner.
Nur, wenn sie fehlt
import sqlite3
def anlegen():
verbindung = sqlite3.connect("laden.db")
verbindung.execute("CREATE TABLE IF NOT EXISTS artikel (name TEXT, preis INTEGER, bestand INTEGER)")
verbindung.close()
print("Die Tabelle artikel ist da")
anlegen() # heute
anlegen() # morgen, laden.db liegt dann noch da CREATE TABLE IF NOT EXISTS legt die Tabelle nur an, wenn es sie noch nicht gibt. Sonst passiert
nichts, auch kein Fehler. Was in der Tabelle steht, bleibt, wie es ist. Diese Zeile steht deshalb am
Anfang fast jedes Programms, das mit einer Datenbank arbeitet.
Man könnte auch auf die Idee kommen, die Datei am Anfang zu löschen oder die Tabelle wegzuwerfen und neu anzulegen. Dann läuft das Programm zwar jedes Mal durch, nimmt aber jedes Mal alles mit, was darin stand. Für ein Beispiel, das jedes Mal frisch anfangen soll, ist das in Ordnung. Für ein Haushaltsbuch wäre es das Ende.
Was die Aufgabe will
Das Haushaltsbuch zieht in eine Datenbank um. Dort braucht es zuerst eine Tabelle, die auch den zweiten Start übersteht. Die eigentliche Entscheidung ist, welche Art von Wert in welche Spalte gehört. In der nächsten Lektion kommen die Ausgaben hinein, danach die Fragen.
Zum Mitnehmen
SQLite legt alles in eine Datei, die man fragt, statt sie zu lesen, und in Python steckt es als Modul sqlite3. connect() öffnet die Datei oder legt sie neu an, execute() schickt einen Befehl in SQL, und dank IF NOT EXISTS klappt das Anlegen auch beim zweiten Start. Datumsangaben stehen als Text wie 2026-09-03 darin, Geldbeträge als ganze Zahl in Cent.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.
Was in dieser Lektion steckt
-
Artikel mit 4 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe, dein Code läuft auf einem Server
Öffnet sich mit dem Basis Konto.