Die weltweit populärste Datenbank brauchte 25 Jahre, um Datentypen zu prüfen

Die weltweit populärste Datenbank brauchte 25 Jahre, um Datentypen zu prüfen

SQLiteDatenbankTypsicherheitSTRICTEntwicklung

Quellen:HN + Evan Hahn blog + web research · HN

Am 27. November 2021 veröffentlichte SQLite Version 3.37.0. Keine Leistungsverdopplung, keine spektakulären neuen Funktionen – lediglich die Möglichkeit, am Ende einer CREATE TABLE-Anweisung ein Wort hinzuzufügen: STRICT.

Was bedeutet das? In einfachen Worten: Ab diesem Tag konnte SQLite endlich eines verweigern – das Eintragen eines Namens in ein Telefonnummernfeld.

Zu diesem Zeitpunkt existierte SQLite bereits seit 21 Jahren. Und es ist die Datenbank, die in jeder App auf Ihrem Smartphone steckt.

SQLite-Logo – die leichtgewichtige Datenbank-Engine treibt weltweit über eine Billion aktive Datenbanken an. Quelle: sqlite.org

Das unsichtbare Fundament in Ihrem Handy

Zunächst eine Klarstellung: SQLite ist keine „App”, die man im App Store herunterlädt. Auf Ihrem Handy gibt es kein SQLite-Symbol. Es ist eine Datenbank-Engine – versteckt im Inneren jeder App, zuständig für das Speichern und Verwalten von Daten.

Chatverläufe in WeChat, Transaktionsdaten in Alipay, Video-Caches von Douyin, das Telefonbuch, die gespeicherten Passwörter im Browser, Offline-Navigationspakete der Karten-App – hinter alledem steht SQLite.

Schätzungen zufolge sind weltweit über eine Billion SQLite-Datenbanken gleichzeitig in Betrieb. Keine andere Datenbank kommt diesem Wert auch nur nahe. SQLite ist der absolute „Weltmeister”.

Doch dieser Champion hat eine kaum zu glaubende „Spezialität”: Er prüft überhaupt nicht, ob die eingegebenen Daten zum deklarierten Typ passen.

„Alter ‘Zhang San’? Kein Problem, bitte.”

Was bedeutet „keine Typprüfung”? Der Autor veranschaulicht es mit einer Alltagsszene.

Sie gehen zur Bank, um ein Konto zu eröffnen. Der Schalterangestellte schiebt Ihnen ein Formular hin. Ein Feld heißt „Alter”, eines „Name”. Sie tragen beim Alter „Zhang San” ein und beim Namen „42” – normalerweise würde der Angestellte das Formular zurückgeben: „Mein Herr, das Alter muss eine Zahl sein, der Name Text.”

SQLite im Standardmodus verhält sich so, als würde der Angestellte einen Blick darauf werfen und mit unbewegter Miene sagen: „In Ordnung, Sie schreiben, ich speichere. Alter ist ‘Zhang San’? Gespeichert. Name ist ‘42’? Auch gut. Das ist Ihre Freiheit.”

In Code übersetzt: Sie erstellen eine Tabelle, deklarieren die Spalte „Alter” als INTEGER und „Name” als TEXT. Dann führen Sie aus:

INSERT INTO Benutzer (Alter) VALUES ('Ich bin keine Zahl');

In MySQL, PostgreSQL und anderen Datenbanken schlägt diese Anweisung sofort fehl. In SQLite? Erfolgreich ausgeführt. Keine Warnung. In Ihrer Datenbank thront in der Spalte „Alter” von nun an der Textwert „Ich bin keine Zahl”.

Das ist kein Randfall. Am 11. Juli 2026 veröffentlichte der Entwickler Evan Hahn einen Blogbeitrag mit dem Titel „Prefer STRICT tables in SQLite”, der auf Hacker News knapp 200 Punkte und 89 Kommentare erhielt. Die Kommentare waren voller Entwickler, die ihre eigenen schmerzhaften Erfahrungen mit dieser Eigenart teilten.

Abbildung 1: Vergleich STRICT-Modus vs. Nicht-STRICT-Modus

STRICT-Modus-Vergleich: Links der Standardmodus (alles wird akzeptiert), rechts der STRICT-Modus (Typfehler werden sofort abgewiesen). Quelle: Autor, basierend auf Evan Hahns Blog und SQLite-Dokumentation

OperationNicht-STRICT (Standard)STRICT-Modus
'abc' in INTEGER-Spalte (Text in Zahlenspalte)✅ Akzeptiert❌ Fehler
'123' in INTEGER-Spalte (Textzahl, verlustfrei konvertierbar)✅ Akzeptiert✅ Akzeptiert
Spaltentyp GARBAGE (Tippfehler / Phantasietyp)✅ Akzeptiert❌ Fehler
Beliebiger Typ in ANY-Spalte✅ Akzeptiert✅ Akzeptiert
CREATE TABLE ohne Spaltentyp✅ Akzeptiert❌ Fehler
Erlaubte TypenUnbegrenztINT, INTEGER, REAL, TEXT, BLOB, ANY

Ein 20-jähriger Philosophiestreit

Dies ist keine Nachlässigkeit oder Faulheit – es war eine bewusste Designentscheidung von SQLite-Schöpfer D. Richard Hipp. Die SQLite-Website widmet dem Thema eine ganze Seite: „Die Vorteile flexibler Typisierung”.

Um diese Entscheidung zu verstehen, muss man ins Jahr 2000 zurückgehen. Hipp arbeitete damals für einen Auftragnehmer der US-Marine und brauchte eine leichtgewichtige Datenbank für Bordsysteme von Kriegsschiffen. Die verfügbaren Lösungen waren entweder zu schwer oder benötigten einen Server – auf einem Kriegsschiff völlig unrealistisch. Also schrieb er seine eigene.

Ein entscheidender Einfluss war TCL – die Programmiersprache, die Hipp am besten kannte. TCL ist eine „dynamisch typisierte” Sprache: Programmierer müssen Variablen nicht vorab einen Typ zuweisen; alles kann als String behandelt werden. Hipp übertrug diese Philosophie auf SQLite: Sie deklarieren einen Spaltentyp? Schön, aber das ist nur eine Empfehlung. Was tatsächlich gespeichert wird, bestimmen Sie.

In den folgenden 20 Jahren entbrannte in der Datenbank-Community eine lange Debatte: Ist flexible Typisierung ein Feature oder ein Bug?

Die Befürworter (Hipp und sein Team) führen drei Kernargumente an:

Erstens: „Ich schreibe seit 35 Jahren Code und habe noch nie einen Bug gesehen, den die Typprüfung verhindert hätte.” Hipp schrieb in der offiziellen Dokumentation, dass er sich bei der jahrzehntelangen Entwicklung von TCL und SQLite an keinen einzigen Fall erinnern könne, in dem das Fehlen von Typbeschränkungen zu einem Programmfehler geführt habe. Seine Schlussfolgerung: Typprüfung sei nur in hardwarenahen Sprachen wie C und C++ nützlich – in einer SQL-Engine, die alle Daten als „Wertobjekte” behandle, helfe Typprüfung nicht viel.

Zweitens: „Die Typprüfung fängt nur triviale Fehler, die ohnehin sofort auffallen.” Dieses Argument ist ziemlich scharf: Dass jemand „Name” ins Feld „Alter” einträgt, würde die Typprüfung zwar abfangen – aber solche Fehler sind so offensichtlich, dass sie bei jedem einfachen Test auffallen. Was Sie wirklich drei Tage Debuggen kostet, ist das Vertauschen von Vor- und Nachnamen – beides Text, die Typprüfung sieht nichts. Hipp argumentierte, dass Typprüfung Entwicklern ein falsches Sicherheitsgefühl gebe, die Daten seien „sauber”.

Drittens: „Flexibilität ermöglicht Dinge, die andere Datenbanken nicht können.” Zum Beispiel: Eine Tabelle als beliebigen Schlüssel-Wert-Speicher nutzen, stillgelegte Spalten für andere Zwecke umwidmen, schmutzige CSV-Dateien aus Excel direkt importieren und später bereinigen.

Die Gegenseite kontert ebenso überzeugend:

„Gerade diese ‘trivialen’ Fehler werden in einer Million Datensätzen zur Nadel im Heuhaufen, die du nie findest. Typprüfung verhindert nicht die Bugs, die du beim Debuggen erwischst – sie verhindert den Moment um 3 Uhr morgens in der Produktion, wenn die Logs keine Fehler zeigen, aber die Benutzerdaten systematisch korrupt werden.”

„Du sagst, du hast in 35 Jahren nie einen Typfehler gesehen? SQLite selbst ist in C geschrieben – beim Kompilieren nutzt du längst die Typprüfung von C. Du verlässt dich auf ein strenges Typsystem, um SQLite selbst fehlerfrei zu halten, aber sagst, Typprüfung sei für andere unwichtig?”

In der HN-Diskussion wurde ein Vergleich immer wieder zitiert: „Das ist wie UDP statt TCP zu verwenden – Geschwindigkeit und Einfachheit gegen Datenintegrität eintauschen, und dann die Wiederholung, Sortierung und Prüfung selbst in der Anwendungsschicht nachzubauen. Wenn du fertig bist, hast du ein schlechteres TCP implementiert.”

Ein anderer Kommentator brachte es noch direkter auf den Punkt: „Für die Leistung kann man Standardwerte opfern. Aber für Korrektheit? Das macht mich nervös.”

Was der STRICT-Modus tatsächlich bewirkt

Zurück zum November 2021. Das Schlüsselwort STRICT bewirkt drei Dinge:

Erstens: Ablehnung typwidriger Einträge. Text in eine Ganzzahlspalte? Fehler. Eine Zahl in eine Textspalte? Erlaubt – Zahlen lassen sich verlustfrei in Text umwandeln. Den String '123' in eine Ganzzahlspalte? Ebenfalls erlaubt – '123' lässt sich perfekt in die Zahl 123 umwandeln. STRICT prüft, ob ein Wert verlustfrei konvertiert werden kann, nicht nur den oberflächlichen Typ. Das ist in mancher Hinsicht klüger als viele streng typisierte Datenbanken.

Zweitens: Ablehnung von Fantasie-Datentypen. Im Nicht-STRICT-Modus können Sie beim Tabellenbau Spaltentypen wie GARBAGE, DATETIME, JSON, UUID oder BLOBB angeben – SQLite akzeptiert sie alle stillschweigend als generischen Typ. Im STRICT-Modus sind nur sechs Typen erlaubt: INT, INTEGER, REAL, TEXT, BLOB, ANY. Wenn Sie sich bei BLOB vertippen und BLOBB schreiben? Wird sofort beanstandet.

Drittens: Wenn Flexibilität nötig ist, gibt es ANY. STRICT ist kein starrer Zwang. Deklarieren Sie eine Spalte als ANY, kann sie jeden beliebigen Datentyp aufnehmen – genau wie im Standardmodus. Der Unterschied: Die Flexibilität wird von Ihnen gezielt zugewiesen, nicht überall als Standard gewährt.

Warum hat es 21 Jahre gedauert?

Von 2000 bis 2021 – 21 Jahre. Warum brauchte ein so grundlegender Prüfmechanismus die gesamte Karriere von zwei Generationen von Entwicklern, um endlich Realität zu werden?

Die Antwort liegt in SQLites Kernversprechen: Rückwärtskompatibilität.

Die SQLite-Entwickler haben eine fast obsessive eiserne Regel: Jeder SQLite-Code, den Sie heute schreiben, muss auch nach einem Upgrade in zehn Jahren zu 100 % funktionieren. Das bedeutet: Das Standardverhalten darf sich nie ändern. Denn eine Änderung könnte bei einer Billion laufender SQLite-Instanzen weltweit zu Problemen führen.

Abbildung 2: Zeitleiste der SQLite-Typsicherheit

2000 ─ SQLite 1.0 veröffentlicht, flexible Typisierung als Kernphilosophie

      │   „Spaltentypen sind Empfehlungen, keine Einschränkungen"

2009 ─ SQLite 3.6.19: Fremdschlüssel-Syntax unterstützt
      │   Aber standardmäßig deaktiviert, muss per PRAGMA foreign_keys = ON aktiviert werden

      │   In den folgenden 12 Jahren wurde der STRICT-Modus mehrfach diskutiert
      │   aber jedes Mal durch die eiserne Regel der Rückwärtskompatibilität blockiert

2021 ─ SQLite 3.37.0: STRICT-Tabellen
      │   STRICT-Schlüsselwort am Ende von CREATE TABLE, pro Tabelle wählbar
      │   Kein globaler Schalter – immer noch die Philosophie „du entscheidest, ob du es willst"

2026 ─ Evan Hahn schreibt: „Bevorzugt STRICT-Tabellen"
      │   HN 199 Punkte, 89 Kommentare – die Debatte geht weiter

Drei Meilensteine über 21 Jahre hinweg, jeder folgt demselben Prinzip: Funktionen können hinzugefügt, aber Standardverhalten darf nicht geändert werden.

Dies ist kein Einzelfall. Fremdschlüssel-Constraints – die verhindern, dass Sie einen Benutzer löschen, während in der Bestelltabelle zehntausend „verwaiste Bestellungen” zurückbleiben – SQLite unterstützt die Syntax seit 2009, aber sie ist bis heute standardmäßig deaktiviert. Bei jeder neuen Datenbankverbindung müssen Sie manuell ausführen:

PRAGMA foreign_keys = ON;

um die Fremdschlüsselprüfung zu aktivieren. Der Grund ist identisch: Eine Änderung des Standardwerts würde die Rückwärtskompatibilität brechen.

In der HN-Diskussion schlug jemand einen Kompromiss vor: Wie ein Browser bei der Erstellung der Datenbank COMPAT_MODE=2026 deklarieren, und neuere Versionen aktivieren automatisch die damaligen empfohlenen Einstellungen. Aber dieser Vorschlag wurde bislang nicht umgesetzt.

Ein Kommentator schrieb einen Satz, der das Dilemma perfekt zusammenfasst: „SQLite ändert extrem selten Standardwerte, weil ihr Rückwärtskompatibilitätsversprechen nahezu heilig ist. Sie wollen nicht, dass eine für SQLite 3.53 geschriebene Software nach dem Upgrade auf 3.54 plötzlich explodiert, weil CREATE TABLE auf einmal STRICT ist.”

Dieser Satz fasst das Dilemma von SQLite präzise zusammen: Auf der einen Seite der Drang, sich ständig zu verbessern, auf der anderen Seite das Gelübde der absoluten Stabilität.

SQLites Erfolg liegt genau darin, dass es sich um nichts kümmert

An dieser Stelle stellt sich eine kontraintuitive Frage: Wenn SQLite so viele „standardmäßig unsichere” Designentscheidungen hat, warum ist es dann die weltweit populärste Datenbank?

Die Antwort liegt in seiner Designphilosophie. SQLites Erfolg kommt zu einem großen Teil daher, dass es sich um nichts kümmert.

Keine Installation, kein Server, keine Konfigurationsdatei. Eine Bibliotheksdatei von wenigen hundert KB, in eine App eingebettet, läuft sofort. Keine Typprüfung – speichere, was du willst. Keine Fremdschlüsselprüfung – wenn etwas schiefgeht, bist du selbst verantwortlich. Keine Transaktionsisolationsstufen – erstmal laufen lassen.

Der Lohn dieser Minimalismus ist: SQLite funktioniert in Smartphones, Browsern, IoT-Sensoren, Routern, Smart-TVs, Auto-Steuergeräten und Flugzeug-Unterhaltungssystemen. Es stellt nie Ansprüche an die Umgebung, verlangt nie Ressourcen, startet nie fehl.

Wie eine Universalsteckdose – jeder Stecker passt hinein. Ob es kurzschließt? Nicht mein Problem.

Die Einführung des STRICT-Modus bedeutet, dass diese Datenbank, die sich 21 Jahre lang „um nichts gekümmert” hat, endlich eine Realität anerkennt: Wenn die Nutzerbasis von einigen Dutzend professionellen C-Programmierern auf Millionen von App-Entwicklern mit sehr unterschiedlichem Kenntnisstand anwächst, wird die standardmäßige „Freiheit” zum standardmäßigen „Risiko”.

Nachwort

Die Geschichte von SQLite ist, im großen Koordinatensystem der Softwareentwicklung betrachtet, ein Abbild der zunehmenden Reife einer ganzen Branche.

Frühe Software richtete sich an wenige professionelle Nutzer. Die Designphilosophie war: „Maximale Freiheit, wenn etwas schiefgeht, ist es dein Problem.” Heute richtet sich Software an Milliarden von Normalanwendern. Der Schwerpunkt des Designs hat sich von „Freiheit” zu „Sicherheit” und „Idiotensicherheit” verschoben.

Der STRICT-Modus ist kein aufregender technischer Durchbruch – was er tut, können MySQL und PostgreSQL seit ihrem ersten Tag. Aber dass er 21 Jahre zu spät kommt, spricht Bände: Viele der selbstverständlichen „Grundfunktionen”, die wir heute für gegeben halten, wurden durch jahrelange, jahrzehntelange Branchenerfahrung, Debatten, Fehlschläge und Rückblicke mühsam errungen.

Wenn das nächste Mal eine App im Hintergrund still und leise Daten in SQLite speichert, denken Sie daran: Dieser unsichtbare Champion, der tausende Tage und Nächte treu in Ihrem Handy arbeitet, hat erst in seinem 21. Lebensjahr eine Fähigkeit erlernt, die jedes Kleinkind im Kindergarten beherrscht –

Steckt keine Schuhe in die Suppenschüssel.


Referenzen: