SQLite cache plus de maths qu'on ne le pense
SQLite a la réputation d'être minimaliste, et pourtant il embarque une panoplie complète de fonctions numériques : arrondi, valeur absolue, plafond et plancher, puissances, racines, logarithmes, trigonométrie, nombres aléatoires. La plupart de ces fonctions mathématiques SQLite ont été ajoutées avec la version 3.35 (2021), donc toute installation un peu récente — celle livrée avec Python, Node, l'ancêtre WebSQL de votre navigateur, ou la CLI officielle — les a déjà sous le coude.
Voici un petit aperçu avant d'entrer dans le vif du sujet :
Six fonctions, une seule ligne de résultats. Le reste de cette page détaille à quoi sert chaque famille et les pièges qui valent le coup d'être connus.
ROUND : celle que vous utiliserez le plus
ROUND(valeur, décimales) arrondit à un nombre donné de décimales. Le second argument est optionnel — sans lui, vous obtenez un arrondi à l'entier le plus proche (mais toujours sous forme de nombre à virgule flottante) :
Quelques points à retenir :
ROUND(3.14159)renvoie3.0, pas3. Pour obtenir un entier, utilisezCAST(ROUND(x) AS INTEGER), ou simplementCAST(x AS INTEGER)pour tronquer.- SQLite applique la règle « arrondi au plus loin de zéro » :
2.5devient3, et-2.5devient-3. Certaines bases utilisent l'arrondi bancaire (vers le pair le plus proche), mais pas SQLite. - L'argument
digitsaccepte des valeurs négatives :ROUND(1234.5, -2)arrondit à la centaine la plus proche et renvoie1200.
En pratique, c'est surtout ROUND(price, 2) que vous écrirez, pour afficher des montants.
ROUND ou CAST : attention, ce n'est pas pareil
Beaucoup de gens dégainent CAST(x AS INTEGER) en pensant arrondir, et se font avoir :
CAST tronque vers zéro — la partie fractionnaire est tout simplement jetée. ROUND, lui, arrondit à l'entier le plus proche. Pour 2.9, l'écart entre les deux est d'une unité entière. À vous de choisir celui qui correspond vraiment au comportement attendu.
ABS, SIGN et le signe d'un nombre
ABS(x) renvoie la valeur absolue. SIGN(x) renvoie -1, 0 ou 1 selon le signe du nombre :
ABS est le couteau suisse — pratique pour les requêtes du genre « quel est l'écart entre ces deux valeurs ? ». SIGN est moins utilisée, mais bien utile quand on veut regrouper des lignes selon leur signe (débit vs crédit, gain vs perte) sans devoir écrire un CASE explicite.
SQLite CEIL, FLOOR et TRUNC
Ces fonctions renvoient des valeurs entières, mais sans arrondir au plus proche. CEIL arrondit toujours vers le haut, FLOOR toujours vers le bas, et TRUNC toujours vers zéro :
Attention aux cas négatifs. FLOOR(-2.9) renvoie -3 (on s'éloigne de zéro), alors que TRUNC(-2.9) donne -2 (on se rapproche de zéro). Sur les nombres négatifs, FLOOR et TRUNC ne sont pas d'accord, et choisir le mauvais des deux est une source classique de bug d'écart d'une unité.
CEILING est un alias de CEIL. Utilisez l'orthographe que vous préférez.
Le vrai piège : la division entière en SQLite
Ce n'est pas une fonction à proprement parler — c'est l'opérateur / — mais c'est ce qui fait trébucher les débutants bien plus que toutes les fonctions mathématiques réunies :
Quand les deux opérandes sont des entiers, SQLite effectue une division entière et tronque le résultat. Dès qu'un côté est un REAL, toute l'expression bascule en réel. La parade : s'assurer qu'au moins un opérande soit un flottant — soit en écrivant 2.0 au lieu de 2, soit en utilisant un cast.
Le piège est particulièrement vicieux avec les références de colonnes : total_cents / 100 renvoie un entier, alors que total_cents / 100.0 te donne bien le montant en euros que vous attendiez.
MOD et l'opérateur %
MOD(x, y) renvoie le reste de la division x / y. L'opérateur % fait exactement la même chose :
MOD(17, 5) et 17 % 5 renvoient tous les deux 2. À noter : le modulo par zéro retourne NULL dans SQLite — pas d'erreur levée, ce qui détonne par rapport à la plupart des langages. Si ce comportement vous pose souci, vérifiez le diviseur en amont ou enveloppez l'appel dans un CASE WHEN y = 0 THEN ... END.
La fonction et l'opérateur sont parfaitement interchangeables. En pratique, la plupart des gens utilisent % parce que c'est plus court.
POWER, SQRT, EXP, LOG : puissances et racines en SQLite
Pour les puissances et les racines carrées :
Quelques pièges classiques à connaître :
POWest un alias dePOWER.- En SQLite,
LOG(x)est en base 10, etLN(x)correspond au logarithme népérien. La forme à deux argumentsLOG(b, x)calcule le logarithme en baseb. (Attention : dans beaucoup de langages,logdésigne le log népérien — ici c'est la convention SQL qui l'a emporté.) SQRTappliqué à un nombre négatif renvoieNULL, pas une erreur.POWER(0, 0)renvoie1par convention.
Ces fonctions sont précieuses dès qu'on touche à des calculs d'intérêts composés, à une normalisation en décibels, à des distances — bref, à toute opération géométrique ou exponentielle.
RANDOM et RANDOMBLOB
RANDOM() renvoie un entier signé sur 64 bits, sur toute la plage de valeurs possibles :
Pour obtenir un nombre dans une plage donnée, on enveloppe l'appel avec ABS (puisque RANDOM() renvoie un entier signé), puis on applique %. Pour obtenir un réel entre 0 et 1, il suffit de diviser par le plus grand entier 64 bits. SQLite ne fournit pas de RAND() natif qui renvoie une valeur entre 0 et 1 — c'est à vous de le construire.
RANDOMBLOB(n) renvoie n octets aléatoires, ce qui est pratique pour générer des jetons de session ou des données de test. Combinez-le avec HEX() pour obtenir une chaîne affichable :
Chaque appel renvoie une nouvelle valeur. Ne comptez pas sur RANDOM() pour produire deux fois le même nombre dans une même ligne — même au sein d'une seule expression, chaque appel est indépendant.
Mise en pratique
Voici un petit exemple concret : calculer des distances et arrondir des prix dans une table de produits.
Le truc important ici, c'est price_cents / 100.0 — le .0 force une division en réel, puis ROUND met en forme avec deux décimales. Sans ça, 1299 / 100 te renverrait 12, et non 12.99.
La suite : les dates et heures
Les fonctions numériques s'occupent des calculs. Les dates et heures, elles, méritent leur propre boîte à outils. SQLite les stocke en TEXT, REAL ou INTEGER, et fournit un petit ensemble de fonctions, modeste mais efficace, pour les parser, les formater et faire de l'arithmétique dessus. C'est ce qu'on verra dans la suite.
Questions fréquentes
Comment arrondir à 2 décimales en SQLite ?
Avec ROUND(valeur, 2). Le second argument indique le nombre de décimales à conserver — ROUND(3.14159, 2) renvoie 3.14. Petit piège : appelé avec un seul argument, ROUND(x) arrondit à l'entier le plus proche mais retourne quand même un nombre flottant, ce qui surprend pas mal de monde.
SQLite propose-t-il CEIL et FLOOR ?
Oui, depuis SQLite 3.35 (2021) les fonctions mathématiques sont intégrées de base : CEIL(x), FLOOR(x), SQRT(x), POWER(x, y), LOG(x), EXP(x), etc. Sur les versions plus anciennes, il faut charger l'extension math — mais la plupart des installations modernes (Python, Node, navigateurs) les activent par défaut.
Pourquoi 5 / 2 renvoie 2 en SQLite ?
Parce que les deux opérandes sont des entiers : SQLite fait alors une division entière et tronque le résultat. Pour obtenir 2.5, il faut convertir un des deux côtés en REAL, par exemple 5 / 2.0 ou CAST(5 AS REAL) / 2. Ce n'est pas spécifique aux fonctions numériques, c'est juste le comportement de l'opérateur / quand ses deux arguments sont entiers.