Menu

SQLite Datentypen: Storage Classes & dynamische Typisierung

Wie SQLite Werte ablegt: die fünf Storage Classes, warum die Typisierung dynamisch ist und welche Stolperfallen besonders Umsteiger von Postgres oder MySQL erwischen.

Diese Seite enthält ausführbare Editoren — bearbeiten, ausführen und Ausgabe sofort sehen.

Fünf Storage Classes statt vieler Datentypen

SQLite speichert jeden Wert in einer von fünf Storage Classes:

  • NULL — kein Wert vorhanden.
  • INTEGER — eine vorzeichenbehaftete Ganzzahl, je nach Größe 1 bis 8 Bytes.
  • REAL — eine 8-Byte-Fließkommazahl nach IEEE-Standard.
  • TEXT — eine Zeichenkette, gespeichert in der Kodierung der Datenbank (meist UTF-8).
  • BLOB — rohe Bytes, exakt so abgelegt, wie du sie übergeben hast.

Mehr gibt es nicht. Kein eigenes BOOLEAN, kein DATETIME, kein VARCHAR, kein DECIMAL. Während andere Datenbanken Dutzende von Typen mitbringen, kommt SQLite mit fünf aus — alles Weitere baut darauf auf.

typeof() zeigt dir die tatsächliche Storage Class jedes Werts an. Du bekommst integer, real, text oder blob zu sehen. Diese vier – plus null – sind alles, was SQLite kennt.

SQLite dynamische Typisierung

Jetzt kommt der Teil, der Umsteiger von Postgres oder MySQL gerne mal aus der Bahn wirft. In SQLite (ohne STRICT) ist der Typ, den du an einer Spalte deklarierst, eher ein Vorschlag als ein verbindlicher Vertrag. Der eigentliche Typ klebt am jeweiligen Wert:

Beide Zeilen wurden akzeptiert. Die Spalte id enthält in einer Zeile einen Integer und in der anderen Text; body hält einmal Text und einmal einen Integer. SQLite speichert Werte jeder Storage Class problemlos in jeder Spalte.

Das ist die dynamische Typisierung von SQLite – eine bewusste Designentscheidung. Sie macht SQLite angenehm nachsichtig, wenn du schnell prototypisierst oder kleine Skripte schreibst. Gleichzeitig kann ein Tippfehler in deinem Anwendungscode dazu führen, dass jahrelang Daten in der falschen Form abgelegt werden, ohne dass es jemand merkt. Wenn dich dieser Kompromiss stört – und bei den meisten produktiven Schemata sollte er das – sind STRICT Tables die Lösung. Dazu kommen wir gleich.

Type Affinity – kurz erklärt

Der deklarierte Typ einer Spalte wird keineswegs ignoriert; er gibt der Spalte eine sogenannte Affinity. Beim Einfügen versucht SQLite, den Wert in Richtung dieser Affinity zu konvertieren, sofern eine verlustfreie Umwandlung möglich ist. Eine TEXT-Spalte, die die Zahl 42 bekommt, behält sie als Text '42'; eine INTEGER-Spalte, die den String '42' erhält, speichert ihn als Integer 42. Würde die Konvertierung Informationen verlieren, bleibt der ursprüngliche Typ erhalten.

Erste Zeile: Die Ganzzahl 42 wurde zu Text '42' umgewandelt, und der String '100' wurde zur Ganzzahl 100. Zweite Zeile: '3.5' ließ sich nicht verlustfrei in INTEGER umwandeln und blieb deshalb als Text erhalten. Dem Thema Type Affinity widmen wir gleich eine eigene Seite — für den Moment reicht es zu wissen, dass der Spaltentyp die Speicherung zwar beeinflusst, aber nicht erzwingt.

Boolean-Werte in SQLite speichern

Eine eigene Storage Class BOOLEAN gibt es in SQLite nicht. Boolesche Werte werden stattdessen als Ganzzahlen abgelegt — 0 für false, 1 für true:

Die Schlüsselwörter TRUE und FALSE werden seit SQLite 3.23 erkannt und intern zu 1 bzw. 0 übersetzt. Eine Spaltendeklaration als BOOLEAN verleiht der Spalte numerische Affinität, schränkt sie aber nicht auf 0/1 ein – ohne STRICT lässt sich problemlos 'maybe' einfügen, und SQLite mault nicht.

Datum und Uhrzeit in SQLite

Einen eigenen Typ DATETIME gibt es ebenfalls nicht. Du entscheidest dich für eine von drei Kodierungen, und die Datumsfunktionen von SQLite kommen mit allen dreien klar:

  • TEXT im ISO-8601-Format: '2026-04-23 14:30:00'.
  • REAL als julianische Tageszahl.
  • INTEGER als Unix-Zeitstempel in Sekunden.

ISO-8601 als Text ist die gängigste Wahl – die Sortierung funktioniert als String korrekt, es ist menschenlesbar, und die eingebauten Funktionen (date(), time(), datetime(), strftime(), julianday()) kommen alle damit klar. Entscheide dich pro Spalte für ein Format und bleib dabei; gemischte Formate in derselben Spalte sind genau die Sorte Problem, die dich ein halbes Jahr später einholt.

VARCHAR, CHAR und andere bekannte Typnamen

SQLite akzeptiert auch die Typnamen, die du aus anderen Datenbanken kennst – VARCHAR(255), CHAR(10), NVARCHAR, DECIMAL(10,2), DOUBLE, FLOAT, INT, BIGINT, MEDIUMINT. Alle werden problemlos geparst. Sie werden lediglich über die Affinitätsregeln auf eine der fünf Storage Classes abgebildet.

VARCHAR(255) erzwingt kein 255-Zeichen-Limit — SQLite ignoriert die Längenangabe schlicht. DECIMAL(10, 2) speichert keine Dezimalzahl mit fester Genauigkeit, sondern erhält numerische Affinität und landet intern als INTEGER oder REAL. Diese Namen existieren nur, damit Schemas aus anderen Datenbanken ohne Anpassung laufen; die Einschränkungen, die anderswo dahinterstehen, bringen sie nicht mit.

Wer für Geldbeträge exakte Dezimalarithmetik braucht, speichert die Beträge als Cent in einem INTEGER-Feld. Bei REAL schleichen sich Fließkomma-Rundungsfehler früher oder später ab der dritten Nachkommastelle ein.

NULL ist eine eigene Storage Class

NULL ist in SQLite nicht einfach „kein Wert", sondern selbst ein Wert mit eigener Storage Class — typeof() gibt das auch genau so zurück:

b taucht als null auf. Das ist wichtig, denn NULL ist mit nichts gleich — nicht einmal mit einem anderen NULL. b = NULL ist also nie wahr; man muss b IS NULL schreiben. Darauf gehen wir später im Kapitel zu Operatoren und NULL genauer ein, aber der Ursprung liegt hier, bei der Storage Class.

Rohdaten speichern mit BLOB

BLOB legt rohe Bytes 1:1 ab — praktisch für kleine Bilder, Hashes, kodierte Daten oder alles, was weder Text noch Zahl ist:

Mit dem Literal x'...' kannst du Blobs in SQL als Hex-Werte schreiben; aus dem Anwendungscode heraus übergibst du normalerweise ein Byte-Array über einen Parameter. length() liefert bei einem Blob die Anzahl der Bytes zurück, nicht die Anzahl der Zeichen.

Ein Hinweis aus der Praxis: SQLite speichert auch große Blobs problemlos, aber wenn du bei jeder Abfrage, die die Zeile berührt, einen 50-MB-Blob mitziehst, wird das richtig langsam. Bei großen Dateien legst du die Datei besser auf der Festplatte ab und speicherst nur den Pfad in der Datenbank.

Was du mitnimmst

  • Fünf Storage Classes — NULL, INTEGER, REAL, TEXT, BLOB — decken alles ab.
  • Booleans sind Integer; Datumswerte speicherst du als Text, Real oder Integer — du entscheidest.
  • Deklarierte Spaltentypen sind Hinweise, keine festen Verträge (es sei denn, du verwendest STRICT).
  • VARCHAR(255) und Konsorten werden zwar geparst, aber die Länge oder Genauigkeit, die sie andernorts suggerieren, wird nicht erzwungen.
  • typeof(value) ist dein bester Freund, wenn du dir nicht sicher bist, was tatsächlich in der Spalte steckt.

Als Nächstes: Type Affinity

Hinter dem „Hinweis"-Verhalten, das wir hier nur angerissen haben, steckt ein klares Regelwerk — fünf Affinitätsklassen, abgeleitet aus dem deklarierten Typnamen, die bei jedem Insert greifen. Genau darum geht es auf der nächsten Seite, und das ist der Schlüssel dazu, vorherzusagen, was SQLite mit deinen Werten wirklich anstellt.

Häufig gestellte Fragen

Welche Datentypen unterstützt SQLite?

SQLite kennt fünf sogenannte Storage Classes: NULL, INTEGER, REAL, TEXT und BLOB. Jeder Wert in der Datenbank landet in genau einer dieser Klassen. Vertraute Bezeichnungen wie VARCHAR(255), DATETIME oder BOOLEAN darfst du in CREATE TABLE zwar weiterhin schreiben — aus Kompatibilitätsgründen — intern werden sie aber auf eine der fünf Klassen abgebildet.

Gibt es in SQLite einen Boolean- oder Datetime-Typ?

Nicht als eigene Storage Class. Boolesche Werte werden als INTEGER (0 und 1) gespeichert, wobei SQLite die Schlüsselwörter TRUE und FALSE ebenfalls versteht. Datums- und Zeitwerte legst du wahlweise als TEXT (ISO-8601-String), REAL (Julianisches Datum) oder INTEGER (Unix-Sekunden) ab — du entscheidest dich für eine Kodierung, und die Datumsfunktionen kommen mit allen drei Varianten klar.

Warum nennt man die Typisierung in SQLite dynamisch?

In den meisten Datenbanken weist eine als INTEGER deklarierte Spalte Strings strikt zurück. In SQLite ist der deklarierte Typ standardmäßig nur ein Hinweis — der tatsächliche Typ hängt am Wert selbst. Heißt: Eine TEXT-Spalte kann durchaus eine Zahl enthalten, wenn du eine einfügst. Mal praktisch, mal eine fiese Stolperfalle. Mit STRICT Tables schaltest du dieses Verhalten ab.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S