SQLite kann mehr Mathe, als du denkst
SQLite gilt als minimalistisch, bringt aber einen kompletten Satz numerischer Funktionen mit: Runden, Absolutbetrag, Auf- und Abrunden, Potenzen, Wurzeln, Logarithmen, Trigonometrie und Zufallszahlen. Die meisten dieser Mathe-Funktionen kamen mit SQLite 3.35 (2021) dazu — jede halbwegs aktuelle Installation hat sie also dabei, egal ob du sie über Python, Node, den offiziellen CLI-Client oder einen anderen modernen Wrapper nutzt.
Vorab ein kleiner Vorgeschmack, bevor wir ins Detail gehen:
Sechs Funktionen, eine Ergebniszeile. Auf dem Rest der Seite gehen wir Schritt für Schritt durch die einzelnen Funktionsfamilien und die Stolperfallen, die du kennen solltest.
ROUND: Die Funktion, die du am häufigsten brauchst
ROUND(value, digits) rundet auf eine bestimmte Anzahl Nachkommastellen. Das zweite Argument ist optional – lässt du es weg, wird auf die nächste ganze Zahl gerundet (das Ergebnis bleibt aber ein Fließkommawert):
Ein paar Dinge, die du dir merken solltest:
ROUND(3.14159)liefert3.0, nicht3. Wenn du wirklich einen Integer willst, nimmCAST(ROUND(x) AS INTEGER)– oder gleichCAST(x AS INTEGER), falls du einfach abschneiden möchtest.- SQLite rundet nach dem Prinzip "kaufmännisch von Null weg":
2.5wird zu3,-2.5zu-3. Manche Datenbanken verwenden das mathematische Runden (Banker's Rounding, also zur nächsten geraden Zahl) – SQLite eben nicht. - Das Argument
digitsdarf auch negativ sein:ROUND(1234.5, -2)rundet auf die nächsten 100, also1200.0.
In der Praxis schreibst du ROUND(price, 2) vermutlich vor allem dann, wenn du Geldbeträge anzeigen willst.
ROUND vs. CAST: zwei verschiedene Welten
Viele greifen zu CAST(x AS INTEGER), wenn sie eigentlich runden wollen – und tappen prompt in die Falle:
CAST schneidet einfach in Richtung Null ab – der Nachkommateil fliegt raus. ROUND rundet dagegen zur nächsten ganzen Zahl. Bei 2.9 liegen also ganze 1.0 zwischen den beiden Ergebnissen. Nimm die Funktion, deren Verhalten du wirklich brauchst.
ABS, SIGN und das Vorzeichen einer Zahl
ABS(x) liefert den Absolutwert. SIGN(x) gibt je nach Vorzeichen -1, 0 oder 1 zurück:
ABS ist der Klassiker – ideal für Abfragen wie „wie weit liegen diese beiden Werte auseinander". SIGN sieht man seltener, ist aber praktisch, wenn du Zeilen nach Vorzeichen gruppieren willst (Soll vs. Haben, Gewinn vs. Verlust), ohne extra ein CASE zu schreiben.
CEIL, FLOOR und TRUNC
Mit diesen Funktionen bekommst du ganzzahlige Werte, ohne kaufmännisch zu runden. CEIL rundet immer auf, FLOOR immer ab, und TRUNC schneidet einfach Richtung Null ab:
Achtung bei negativen Werten: FLOOR(-2.9) ergibt -3 (weiter weg von Null), während TRUNC(-2.9) -2 liefert (also Richtung Null gerundet). Sobald negative Zahlen ins Spiel kommen, gehen FLOOR und TRUNC getrennte Wege – und die falsche Wahl führt zum klassischen Off-by-One-Bug.
CEILING ist übrigens nur ein Alias für CEIL. Nimm einfach die Schreibweise, die dir besser gefällt.
Die eigentliche Stolperfalle: Integer-Division in SQLite
Streng genommen ist das gar keine Funktion, sondern der /-Operator – aber er sorgt bei Einsteigern für mehr Verwirrung als sämtliche Mathe-Funktionen zusammen:
Sobald beide Seiten Integer sind, macht SQLite eine Integer-Division und schneidet einfach ab. Sobald aber eine Seite ein REAL ist, wird der ganze Ausdruck zu einem Fließkommawert. Die Lösung: Mindestens einer der Operanden muss ein Float sein – entweder schreibst du 2.0 statt 2, oder du castest explizit.
Besonders fies wird das bei Spaltenreferenzen: total_cents / 100 liefert dir einen Integer zurück. total_cents / 100.0 ergibt dagegen den Dollarbetrag, den du eigentlich haben wolltest.
MOD und der %-Operator
MOD(x, y) gibt den Rest aus x / y zurück. Der Modulo-Operator % macht genau dasselbe:
MOD(17, 5) und 17 % 5 liefern beide 2. Modulo durch null gibt in SQLite NULL zurück – es wird also kein Fehler geworfen, was im Vergleich zu den meisten anderen Sprachen schon ungewöhnlich ist. Wenn dir das wichtig ist, prüfe den Divisor vorher oder pack den Aufruf in ein CASE WHEN y = 0 THEN ... END.
Funktion und Operator sind austauschbar. In der Praxis greifen die meisten zu %, einfach weil es kürzer ist.
POWER, SQRT, EXP, LOG
Für Potenzen und Wurzeln:
Ein paar Stolperfallen, über die viele stolpern:
POWist nur ein Alias fürPOWER.LOG(x)rechnet in SQLite mit Basis 10. Den natürlichen Logarithmus bekommst du überLN(x). Mit zwei Argumenten –LOG(b, x)– wird der Logarithmus zur Basisbberechnet. (Das weicht von vielen Programmiersprachen ab, in denenlogfür den natürlichen Logarithmus steht – die SQL-Konvention hat sich hier durchgesetzt.)SQRTeiner negativen Zahl liefertNULLzurück, keinen Fehler.POWER(0, 0)ergibt per Konvention1.
Praktisch wird das überall dort, wo geometrische oder exponentielle Berechnungen ins Spiel kommen: Zinseszinsen, Normalisierung auf Dezibel, Distanzberechnungen und so weiter.
Zufallszahlen mit RANDOM und RANDOMBLOB
RANDOM() liefert einen vorzeichenbehafteten 64-Bit-Integer aus dem kompletten Wertebereich:
Um eine Zahl in einem bestimmten Bereich zu bekommen, packst du RANDOM() in ABS ein (da RANDOM() vorzeichenbehaftet ist) und verwendest %. Für eine Fließkommazahl zwischen 0 und 1 teilst du das Ergebnis durch den maximalen 64-Bit-Integer. SQLite bringt nämlich keine eingebaute RAND()-Funktion mit, die 0–1 liefert – das musst du dir selbst zusammenbauen.
RANDOMBLOB(n) gibt n zufällige Bytes zurück und ist praktisch, um Session-Tokens oder Testdaten zu erzeugen. Kombiniert mit HEX() bekommst du einen druckbaren String:
Jeder Aufruf liefert einen neuen Wert. Verlasse dich also nicht darauf, dass RANDOM() innerhalb derselben Zeile zweimal dieselbe Zahl zurückgibt – selbst innerhalb eines einzigen Ausdrucks ist jeder Aufruf für sich unabhängig.
Alles zusammen in einem Beispiel
Ein kleines durchgerechnetes Beispiel: Entfernungen berechnen und Preise runden für eine Produkttabelle.
Der entscheidende Trick steckt in price_cents / 100.0 — das .0 erzwingt eine Division mit Fließkommazahlen, und ROUND bringt das Ergebnis dann auf zwei Nachkommastellen. Ohne den Punkt würde 1299 / 100 schlicht 12 liefern, nicht 12.99.
Weiter geht's mit Datum und Zeit
Mit den numerischen Funktionen ist die Mathematik abgedeckt. Für Datum und Uhrzeit braucht es aber eigenes Werkzeug — SQLite legt solche Werte als Text, Real oder Integer ab und stellt dafür ein überschaubares, aber durchaus mächtiges Set an Funktionen zum Parsen, Formatieren und Rechnen bereit. Genau darum geht es im nächsten Abschnitt.
Häufig gestellte Fragen
Wie runde ich in SQLite auf 2 Nachkommastellen?
Mit ROUND(value, 2). Das zweite Argument legt fest, wie viele Nachkommastellen erhalten bleiben — ROUND(3.14159, 2) liefert 3.14. Ruft man ROUND(x) ohne zweites Argument auf, wird zwar auf die nächste ganze Zahl gerundet, das Ergebnis ist aber trotzdem ein Float — das überrascht viele.
Gibt es CEIL und FLOOR in SQLite?
Ja, seit SQLite 3.35 (2021) sind die Mathe-Funktionen direkt eingebaut: CEIL(x), FLOOR(x), SQRT(x), POWER(x, y), LOG(x), EXP(x) und einige mehr. Bei älteren Builds funktionieren sie nur, wenn die Math-Extension geladen ist — die meisten gängigen Installationen (Python, Node, Browser) bringen sie aber bereits aktiviert mit.
Warum liefert 5 / 2 in SQLite den Wert 2?
Weil beide Operanden Integer sind, macht SQLite eine Integer-Division und schneidet die Nachkommastellen ab. Caste eine Seite nach REAL — also 5 / 2.0 oder CAST(5 AS REAL) / 2 — und du bekommst 2.5. Das ist keine Eigenheit der numerischen Funktionen, sondern schlicht das Verhalten des /-Operators bei Integer-Argumenten.