10. Fonctions SQL
Ce chapitre décrit toutes les fonctions et tous les opérateurs SQL intégrés de MIRAJ en langage MIRAJ : leur signature, leur comportement précis, leur type de retour, leur comportement face à NULL et un exemple d'appel avec son résultat. Les résultats sont ceux affichés par la console miraj-cli (les chaînes sont écrites ici entre apostrophes pour les distinguer des nombres).
10.0 Généralités#
- Noms insensibles à la casse.
CONCAT,Concatetconcatdésignent la même fonction. Ce chapitre les écrit en majuscules par convention. - Propagation de
NULL. Sauf mention contraire explicite dans la description d'une fonction, tout argumentNULLrend le résultatNULL. Les exceptions notables sontCOALESCE,IFNULL/NVL,CONCAT_WS,IF,ISNULL,ELT,FIELD,MAKE_SET,QUOTE,SFORMAT(pour les arguments autres que le format) et les agrégats (qui ignorent lesNULLde leur argument plutôt que de propagerNULLpour toute la ligne). - Positions et longueurs de chaînes sont comptées en caractères Unicode (pas en octets), sauf
LENGTHetBIT_LENGTHqui comptent des octets UTF-8.ASCIIrenvoie l'octet de tête de l'encodage UTF-8 du premier caractère ;ORDcombine les octets UTF-8 du premier caractère en gros-boutiste (ORD('é')= 50089, alors queéa le point de code Unicode 233). - CASE WHEN n'est pas une fonction mais une construction du langage SQL (voir le chapitre 9. Requêtes SELECT) ; son comportement de typage de résultat suit les mêmes règles que
COALESCE/IFdécrites en 10.4. - Ce chapitre documente l'intégralité des fonctions scalaires du moteur, les fonctions d'agrégation et de fenêtrage, et les opérateurs (10.19). Un nom inconnu rend l'erreur 1305 (
FUNCTION nom does not exist), un mauvais nombre d'arguments l'erreur 1582.
Table des matières#
- 10.1 Fonctions de chaînes de caractères
- CONCAT · CONCAT_WS · UPPER / UCASE · LOWER / LCASE · LENGTH / OCTET_LENGTH / LENGTHB · BIT_LENGTH · CHAR_LENGTH / CHARACTER_LENGTH · TRIM · LTRIM · RTRIM · SUBSTRING / SUBSTR / MID · LEFT · RIGHT · REPLACE · LOCATE · INSTR · LPAD · RPAD · REVERSE · REPEAT · SPACE · ASCII · ORD · CHAR · CHR · STRCMP · FORMAT · INSERT · ELT · FIELD · FIND_IN_SET · SUBSTRING_INDEX · QUOTE · BIN · OCT · CONV · MAKE_SET · EXPORT_SET · SOUNDEX · NATURAL_SORT_KEY · WEIGHT_STRING · LOAD_FILE · CONVERT (jeu de caractères) · FORMAT_BYTES · FORMAT_PICO_TIME
- 10.2 Fonctions numériques
- 10.3 Fonctions de date et heure
- NOW / CURRENT_TIMESTAMP / LOCALTIME / LOCALTIMESTAMP · SYSDATE · CURDATE / CURRENT_DATE · CURTIME / CURRENT_TIME · UTC_TIMESTAMP, UTC_DATE, UTC_TIME · DATE · TIME · TIMESTAMP · YEAR · MONTH · DAY / DAYOFMONTH · HOUR · MINUTE · SECOND · MICROSECOND · DAYOFWEEK · WEEKDAY · DAYOFYEAR · QUARTER · WEEK · WEEKOFYEAR · YEARWEEK · DAYNAME · MONTHNAME · LAST_DAY · DATE_FORMAT / TIME_FORMAT · TO_CHAR · STR_TO_DATE · DATE_ADD / ADDDATE · DATE_SUB / SUBDATE · ADD_MONTHS · MONTHS_BETWEEN · TIMESTAMPADD · DATEDIFF · TIMEDIFF · TIMESTAMPDIFF · ADDTIME · SUBTIME · UNIX_TIMESTAMP · FROM_UNIXTIME · TO_DAYS · FROM_DAYS · MAKEDATE · MAKETIME · TIME_TO_SEC · SEC_TO_TIME · EXTRACT · TO_SECONDS · PERIOD_ADD · PERIOD_DIFF · GET_FORMAT · CONVERT_TZ
- 10.4 Fonctions de contrôle et logique
- IF · IFNULL / NVL · COALESCE · NULLIF · ISNULL · NVL2 · INTERVAL (rang) · DEFAULT · NAME_CONST
- 10.5 Fonctions d'agrégation
- 10.6 Expressions régulières
- 10.7 Fonctions de hachage, chiffrement et encodage
- MD5 · SHA1 / SHA · SHA2 · PASSWORD · HEX · UNHEX · TO_BASE64 · FROM_BASE64 · AES_ENCRYPT · AES_DECRYPT · COMPRESS · UNCOMPRESS · UNCOMPRESSED_LENGTH · OLD_PASSWORD · ENCODE / DECODE · DES_ENCRYPT / DES_DECRYPT · ENCRYPT · KDF
- 10.8 Fonctions réseau (IP)
- INET_ATON · INET_NTOA · INET6_ATON · INET6_NTOA · IS_IPV4 · IS_IPV6 · IS_IPV4_COMPAT · IS_IPV4_MAPPED
- 10.9 Fonctions système, session et verrous
- DATABASE / SCHEMA · VERSION · CHARSET · COLLATION · COERCIBILITY · BENCHMARK · LAST_INSERT_ID · ROW_COUNT · FOUND_ROWS · CONNECTION_ID · USER / SESSION_USER / SYSTEM_USER · CURRENT_USER · CURRENT_ROLE · SLEEP · UUID / UUID_V4 · UUID_V7 · SYS_GUID · RANDOM_BYTES · UUID_SHORT · GET_LOCK · RELEASE_LOCK · IS_FREE_LOCK · IS_USED_LOCK · RELEASE_ALL_LOCKS · MIRAJ_NOTIFY · MIRAJ_CHANGE_SEQ · BINLOG_GTID_POS · MASTER_GTID_WAIT · MASTER_POS_WAIT · DECODE_HISTOGRAM · Variables système
@@nom
- DATABASE / SCHEMA · VERSION · CHARSET · COLLATION · COERCIBILITY · BENCHMARK · LAST_INSERT_ID · ROW_COUNT · FOUND_ROWS · CONNECTION_ID · USER / SESSION_USER / SYSTEM_USER · CURRENT_USER · CURRENT_ROLE · SLEEP · UUID / UUID_V4 · UUID_V7 · SYS_GUID · RANDOM_BYTES · UUID_SHORT · GET_LOCK · RELEASE_LOCK · IS_FREE_LOCK · IS_USED_LOCK · RELEASE_ALL_LOCKS · MIRAJ_NOTIFY · MIRAJ_CHANGE_SEQ · BINLOG_GTID_POS · MASTER_GTID_WAIT · MASTER_POS_WAIT · DECODE_HISTOGRAM · Variables système
- 10.10 Fonctions JSON
- JSON_OBJECT · JSON_ARRAY · JSON_MERGE_PRESERVE / JSON_MERGE · JSON_MERGE_PATCH · JSON_QUOTE · JSON_VALID · Chemins JSON · Opérateurs
->et->>· JSON_EXTRACT · JSON_UNQUOTE · JSON_VALUE · JSON_SET / JSON_INSERT / JSON_REPLACE · JSON_REMOVE · JSON_ARRAY_APPEND / JSON_ARRAY_INSERT · JSON_CONTAINS · JSON_CONTAINS_PATH · JSON_KEYS · JSON_LENGTH · JSON_DEPTH · JSON_TYPE · JSON_SEARCH · JSON_OVERLAPS · MEMBER OF · JSON_PRETTY · JSON_QUERY · JSON_EXISTS · JSON_EQUALS · JSON_NORMALIZE · JSON_COMPACT / JSON_LOOSE / JSON_DETAILED · JSON_ARRAY_INTERSECT · JSON_OBJECT_FILTER_KEYS · JSON_OBJECT_TO_ARRAY · JSON_KEY_VALUE · JSON_SCHEMA_VALID / JSON_SCHEMA_VALIDATION_REPORT · JSON_TABLE
- JSON_OBJECT · JSON_ARRAY · JSON_MERGE_PRESERVE / JSON_MERGE · JSON_MERGE_PATCH · JSON_QUOTE · JSON_VALID · Chemins JSON · Opérateurs
- 10.11 Fonctions vectorielles (VECTOR(n))
- VEC_FROMTEXT · VEC_TOTEXT · VEC_DISTANCE_EUCLIDEAN · VEC_DISTANCE_COSINE · VEC_DISTANCE · STRING_TO_VECTOR / TO_VECTOR · VECTOR_TO_STRING / FROM_VECTOR · VECTOR_DIM · DISTANCE · L2_DISTANCE · COSINE_DISTANCE · INNER_PRODUCT · VECTOR_NEGATIVE_INNER_PRODUCT · L1_DISTANCE · VECTOR_DIMS · VECTOR_NORM · L2_NORMALIZE · SUBVECTOR · VECTOR_ADD · VECTOR_SUB · VECTOR_MUL
- 10.12 Mise en forme avancée
- 10.13 Fonctions de fenêtrage
- 10.14 Colonnes dynamiques
- 10.15 Fonctions de séquence
- 10.16 Recherche plein texte (
MATCH … AGAINST) - 10.17 Fonctions spatiales
- 10.18 Fonctions XML
- 10.19 Opérateurs
- Arithmétiques · Comparaison · Logiques · Bit à bit · Motifs · Autres · Conversion de type · Priorité
10.1 Fonctions de chaînes de caractères#
Récapitulatif :
| Fonction | Signature |
|---|---|
| CONCAT | CONCAT(chaine1, chaine2, ...) |
| CONCAT_WS | CONCAT_WS(separateur, chaine1, chaine2, ...) |
| UPPER / UCASE | UPPER(chaine) |
| LOWER / LCASE | LOWER(chaine) |
| LENGTH / OCTET_LENGTH / LENGTHB | LENGTH(chaine) |
| BIT_LENGTH | BIT_LENGTH(chaine) |
| CHAR_LENGTH / CHARACTER_LENGTH | CHAR_LENGTH(chaine) |
| TRIM | TRIM([BOTH | LEADING | TRAILING] [caracteres] FROM chaine) <br> TRIM(chaine) <br> TRIM(caracteres, chaine) |
| LTRIM | LTRIM(chaine) |
| RTRIM | RTRIM(chaine) |
| SUBSTRING / SUBSTR / MID | SUBSTRING(chaine, position [, longueur]) |
| LEFT | LEFT(chaine, n) |
| RIGHT | RIGHT(chaine, n) |
| REPLACE | REPLACE(chaine, recherche, remplacement) |
| LOCATE | LOCATE(sous_chaine, chaine [, position_depart]) |
| INSTR | INSTR(chaine, sous_chaine) |
| LPAD | LPAD(chaine, longueur, remplissage) |
| RPAD | RPAD(chaine, longueur, remplissage) |
| REVERSE | REVERSE(chaine) |
| REPEAT | REPEAT(chaine, n) |
| SPACE | SPACE(n) |
| ASCII | ASCII(chaine) |
| ORD | ORD(chaine) |
| CHAR | CHAR(code1 [, code2, ...]) |
| CHR | CHR(code) |
| STRCMP | STRCMP(chaine1, chaine2) |
| FORMAT | FORMAT(nombre, decimales [, locale]) |
| INSERT | INSERT(chaine, position, longueur, remplacement) |
| ELT | ELT(n, chaine1, chaine2, ...) |
| FIELD | FIELD(chaine, valeur1, valeur2, ...) |
| FIND_IN_SET | FIND_IN_SET(chaine, liste) |
| SUBSTRING_INDEX | SUBSTRING_INDEX(chaine, delimiteur, n) |
| QUOTE | QUOTE(chaine) |
| BIN | BIN(n) |
| OCT | OCT(n) |
| CONV | CONV(nombre, base_origine, base_cible) |
| MAKE_SET | MAKE_SET(masque, chaine1, chaine2, ...) |
| EXPORT_SET | EXPORT_SET(masque, on, off [, separateur [, nb_bits]]) |
| SOUNDEX | SOUNDEX(chaine) |
| NATURAL_SORT_KEY | NATURAL_SORT_KEY(chaine) |
| WEIGHT_STRING | WEIGHT_STRING(chaine) <br> WEIGHT_STRING(chaine AS CHAR(n)) <br> WEIGHT_STRING(chaine AS BINARY(n)) |
| LOAD_FILE | LOAD_FILE(chemin) |
| CONVERT (jeu de caractères) | CONVERT(expr USING jeu_de_caracteres) <br> CAST(expr AS CHAR CHARACTER SET jeu_de_caracteres) |
| FORMAT_BYTES | FORMAT_BYTES(octets) |
| FORMAT_PICO_TIME | FORMAT_PICO_TIME(picosecondes) |
| POSITION | POSITION(sous_chaine IN chaine) |
CONCAT#
CONCAT(chaine1, chaine2, ...)Concatène de un à un nombre illimité d'arguments, convertis en texte si besoin. NULL propage : si un seul argument est NULL, le résultat entier est NULL (contrairement à CONCAT_WS). Si l'un des arguments est une chaîne binaire (VARBINARY, BLOB, X'…', résultat de COMPRESS…), le résultat en est une : les octets de chaque argument sont mis bout à bout tels quels.
Retour : VARCHAR/texte.
SELECT CONCAT('MIRAJ', ' ', 'DB'); -- 'MIRAJ DB'
SELECT CONCAT('a', NULL, 'b'); -- NULLCONCAT_WS#
CONCAT_WS(separateur, chaine1, chaine2, ...)« Concat With Separator » : concatène chaine1, chaine2, ... en insérant separateur entre chaque paire d'arguments non NULL ; un argument NULL est simplement ignoré (pas d'insertion vide). Si separateur lui-même est NULL, le résultat est NULL.
Retour : texte.
SELECT CONCAT_WS(',', 'a', NULL, 'b'); -- 'a,b'
SELECT CONCAT_WS(NULL, 'a', 'b'); -- NULLUPPER / UCASE#
UPPER(chaine)Met chaine en majuscules (règles Unicode, pas seulement ASCII). UCASE est un alias strict.
Retour : texte. NULL → NULL.
SELECT UPPER('café'); -- 'CAFÉ'LOWER / LCASE#
LOWER(chaine)Met chaine en minuscules (règles Unicode). LCASE est un alias strict.
SELECT LOWER('CAFÉ'); -- 'café'LENGTH / OCTET_LENGTH / LENGTHB#
LENGTH(chaine)Longueur de chaine en octets de son encodage UTF-8 (pas en caractères) ; pour une valeur binaire (VARBINARY/BLOB), longueur en octets bruts, sans passer par un décodage UTF-8. OCTET_LENGTH et LENGTHB sont des alias stricts.
Retour : BIGINT.
SELECT LENGTH('café'); -- 5 (le é occupe deux octets en UTF-8)BIT_LENGTH#
BIT_LENGTH(chaine)Longueur en bits, soit huit fois LENGTH(chaine).
SELECT BIT_LENGTH('a'); -- 8CHAR_LENGTH / CHARACTER_LENGTH#
CHAR_LENGTH(chaine)Longueur de chaine en caractères Unicode (pas en octets) ; pour une valeur binaire, un octet compte pour un caractère. CHARACTER_LENGTH est un alias strict.
SELECT CHAR_LENGTH('café'); -- 4TRIM#
TRIM([BOTH | LEADING | TRAILING] [caracteres] FROM chaine)
TRIM(chaine)
TRIM(caracteres, chaine)Retire les occurrences répétées de caracteres (l'espace ' ' par défaut, avec la forme à un argument) en tête, en fin, ou des deux côtés (BOTH, valeur par défaut) de chaine. Si caracteres est une chaîne vide, chaine est rendue inchangée.
Retour : texte.
SELECT TRIM(' x '); -- 'x'
SELECT TRIM(LEADING '0' FROM '007'); -- '7'
SELECT TRIM(BOTH 'xy' FROM 'xyzxy'); -- 'z'LTRIM#
LTRIM(chaine)Retire les espaces (' ') en tête de chaine uniquement.
SELECT LTRIM(' x '); -- 'x 'RTRIM#
RTRIM(chaine)Retire les espaces (' ') en fin de chaine uniquement.
SELECT RTRIM(' x '); -- ' x'SUBSTRING / SUBSTR / MID#
SUBSTRING(chaine, position [, longueur])Sous-chaîne de chaine à partir du caractère position (1 = premier caractère). Une position négative compte depuis la fin (-1 = dernier caractère). Sans longueur, va jusqu'à la fin ; avec longueur < 1 ou position = 0 ou position hors de la chaîne, rend une chaîne vide (pas NULL). SUBSTR et MID sont des alias stricts. Sur une chaîne binaire, les positions et la longueur comptent des octets et le résultat est une chaîne binaire (de même pour LEFT et RIGHT).
Retour : texte.
SELECT SUBSTRING('MIRAJ DB', 7); -- 'DB'
SELECT SUBSTRING('MIRAJ DB', 1, 5); -- 'MIRAJ'
SELECT SUBSTRING('MIRAJ DB', -2); -- 'DB'LEFT#
LEFT(chaine, n)Les n premiers caractères de chaine (n négatif traité comme 0 ; n au-delà de la longueur rend chaine entière).
SELECT LEFT('MIRAJ', 3); -- 'MIR'RIGHT#
RIGHT(chaine, n)Les n derniers caractères de chaine.
SELECT RIGHT('MIRAJ', 3); -- 'RAJ'REPLACE#
REPLACE(chaine, recherche, remplacement)Remplace toutes les occurrences non chevauchantes de recherche par remplacement dans chaine, en respectant la casse. Si recherche est une chaîne vide, chaine est rendue inchangée (pas de boucle infinie).
SELECT REPLACE('a-b-c', '-', '/'); -- 'a/b/c'LOCATE#
LOCATE(sous_chaine, chaine [, position_depart])Position (en caractères, base 1) de la première occurrence de sous_chaine dans chaine, recherche selon l'interclassement résolu : en utf8mb4_general_ci (défaut) insensible à la casse mais sensible aux accents (LOCATE('eme', 'Crème') rend 0) ; en utf8mb4_unicode_ci et utf8mb4_bin, chaque fenêtre de même longueur en octets que sous_chaine est comparée sous l'interclassement (LOCATE('ss', 'Straße' COLLATE utf8mb4_unicode_ci) rend 5, LOCATE('a', 'A' COLLATE utf8mb4_bin) rend 0 ; voir Interclassements), à partir de position_depart (1 par défaut). Rend 0 si sous_chaine n'est pas trouvée ou si position_depart < 1.
SELECT LOCATE('DB', 'MIRAJ DB'); -- 7
SELECT LOCATE('xyz', 'MIRAJ DB'); -- 0INSTR#
INSTR(chaine, sous_chaine)Équivalent à LOCATE(sous_chaine, chaine) (ordre des arguments inversé), recherche depuis le début, selon l'interclassement comme LOCATE. La forme normalisée POSITION(sous_chaine IN chaine) est un autre synonyme.
SELECT INSTR('MIRAJ DB', 'DB'); -- 7
SELECT POSITION('DB' IN 'MIRAJ DB'); -- 7LPAD#
LPAD(chaine, longueur, remplissage)Complète chaine à gauche avec des répétitions de remplissage jusqu'à longueur caractères ; si chaine compte déjà longueur caractères ou plus, elle est tronquée à longueur caractères. Rend NULL si longueur < 0 ou dépasse un million de caractères ; rend une chaîne vide si remplissage est vide et qu'il faudrait compléter.
SELECT LPAD('7', 3, '0'); -- '007'
SELECT LPAD('12345', 3, '0'); -- '123' (tronqué)RPAD#
RPAD(chaine, longueur, remplissage)Comme LPAD mais complète à droite.
SELECT RPAD('7', 3, '0'); -- '700'REVERSE#
REVERSE(chaine)Inverse l'ordre des caractères (Unicode) de chaine.
SELECT REVERSE('MIRAJ'); -- 'JARIM'REPEAT#
REPEAT(chaine, n)Répète chaine n fois bout à bout (n négatif traité comme 0). Rend NULL si n dépasse un million, ou si le résultat dépasserait 64 Mio (valeur par défaut de max_allowed_packet).
SELECT REPEAT('ab', 3); -- 'ababab'SPACE#
SPACE(n)Chaîne de n espaces (n négatif traité comme 0). Rend NULL si n dépasse un million.
SELECT SPACE(3); -- ' 'ASCII#
ASCII(chaine)Octet de tête de l'encodage UTF-8 du premier caractère de chaine (donc le code ASCII pour un caractère ASCII ; pour un caractère multi-octets, seul l'octet de tête est rendu, pas le point de code Unicode). 0 si chaine est vide.
Retour : BIGINT.
SELECT ASCII('A'); -- 65ORD#
ORD(chaine)Code numérique du premier caractère de chaine, calculé en combinant ses octets UTF-8 en gros-boutiste. Pour un caractère ASCII, identique à ASCII. 0 si chaine est vide.
SELECT ORD('A'); -- 65
SELECT ORD('é'); -- 50089 (0xC3 0xA9 combinés)CHAR#
CHAR(code1 [, code2, ...])Construit une chaîne à partir de points de code (chaque argument devient un caractère). Un argument NULL est ignoré (ne casse pas la concaténation, contrairement à la plupart des fonctions de chaînes). Chaque code est d'abord interprété comme les octets significatifs d'un caractère multi-octets ; si le résultat n'est pas de l'UTF-8 valide, chaque code est relu comme un point de code Unicode direct.
SELECT CHAR(77, 73, 82, 65, 74); -- 'MIRAJ'CHR#
CHR(code)Le caractère dont code est le code dans le jeu de caractères de la base (utf8mb4) : équivaut à CHAR(code USING utf8mb4) à un seul argument. code est lu comme les octets significatifs du caractère (CHR(65) vaut 'A', CHR(50089) vaut 'é', dont l'encodage est C3 A9), et non comme un point de code Unicode. Si ces octets ne forment pas de l'UTF-8 valide (CHR(233)), le résultat est NULL avec l'avertissement 1300.
Retour : texte.
SELECT CHR(65), CHR(50089); -- 'A', 'é'STRCMP#
STRCMP(chaine1, chaine2)Compare deux chaînes selon l'interclassement résolu de ses arguments (STRCMP('a' COLLATE utf8mb4_bin, 'A') rend 1) : 0 si égales, un nombre négatif si chaine1 < chaine2, positif sinon.
Retour : BIGINT.
SELECT STRCMP('a', 'b'); -- -1
SELECT STRCMP('a', 'a'); -- 0FORMAT#
FORMAT(nombre, decimales [, locale])Met nombre en forme avec decimales chiffres après la virgule (arrondi à la valeur la plus proche, moitié éloignée de zéro ; decimales borné à 0–38) et un séparateur de milliers. Pour un flottant (DOUBLE, PI(), littéral en notation scientifique), nombre × 10^decimales est arrondi à l'entier pair le plus proche (FORMAT(2.5e0, 0) vaut '2') et le résultat s'écrit avec ses chiffres significatifs les plus courts, complétés de zéros (FORMAT(PI(), 38) vaut '3.14159265358979300000000000000000000000') ; un flottant négatif arrondi à zéro garde son signe (FORMAT(-0.004e0, 2) vaut '-0.00'). Sans locale, utilise les conventions anglo-américaines (, pour les milliers, . pour la décimale). Avec une locale reconnue (par ex. 'fr_FR', 'de_DE'), les séparateurs et le groupement des chiffres suivent cette locale ; une locale inconnue ou NULL équivaut à 'en_US'. NULL si nombre ou decimales est NULL.
Retour : texte.
SELECT FORMAT(1234567.891, 2); -- '1,234,567.89'
SELECT FORMAT(1234567.891, 2, 'fr_FR'); -- '1234567,89' (fr_FR ne groupe pas les milliers)
SELECT FORMAT(1234567.891, 2, 'de_DE'); -- '1.234.567,89'INSERT#
INSERT(chaine, position, longueur, remplacement)Remplace longueur caractères de chaine à partir de position (base 1) par remplacement. Si position est hors de chaine (< 1 ou > longueur(chaine)), chaine est rendue inchangée. Une longueur négative va jusqu'à la fin de chaine.
SELECT INSERT('MIRAJ DB', 7, 2, 'Serveur'); -- 'MIRAJ Serveur'ELT#
ELT(n, chaine1, chaine2, ...)Rend la n-ième chaîne (base 1) parmi chaine1, chaine2, .... Rend NULL si n est NULL, hors de portée (< 1 ou > le nombre de chaînes) ou si la chaîne choisie est NULL — mais les autres NULL de la liste n'affectent pas le résultat s'ils ne sont pas choisis.
SELECT ELT(2, 'a', 'b', 'c'); -- 'b'
SELECT ELT(5, 'a', 'b', 'c'); -- NULLFIELD#
FIELD(chaine, valeur1, valeur2, ...)Position (base 1) de chaine dans la liste valeur1, valeur2, ... (comparaison insensible à la casse), 0 si non trouvée. Rend 0 (pas NULL) si chaine est NULL ; une valeurN NULL est ignorée sans jamais correspondre.
SELECT FIELD('b', 'a', 'b', 'c'); -- 2
SELECT FIELD('x', 'a', 'b', 'c'); -- 0FIND_IN_SET#
FIND_IN_SET(chaine, liste)Position (base 1) de chaine dans liste, une chaîne de valeurs séparées par des virgules ; 0 si non trouvée ou si liste est vide.
SELECT FIND_IN_SET('b', 'a,b,c'); -- 2SUBSTRING_INDEX#
SUBSTRING_INDEX(chaine, delimiteur, n)Si n > 0, tout ce qui précède la n-ième occurrence de delimiteur depuis le début ; si n < 0, tout ce qui suit la |n|-ième occurrence depuis la fin. Rend chaine entière si delimiteur n'apparaît pas assez de fois. Rend une chaîne vide si delimiteur est vide ou n vaut 0.
SELECT SUBSTRING_INDEX('a.b.c.d', '.', 2); -- 'a.b'
SELECT SUBSTRING_INDEX('a.b.c.d', '.', -2); -- 'c.d'QUOTE#
QUOTE(chaine)Entoure chaine d'apostrophes et échappe les apostrophes et antislashs qu'elle contient, pour produire un littéral SQL réutilisable directement dans une instruction. Ne propage pas NULL : QUOTE(NULL) rend la chaîne littérale 'NULL' (quatre lettres, sans guillemets), le mot-clé SQL tel qu'il apparaîtrait dans une instruction.
SELECT QUOTE("l'ami"); -- 'l\'ami' (apostrophes comprises dans le texte rendu)
SELECT QUOTE(NULL); -- 'NULL' (le texte de quatre lettres, pas la valeur SQL NULL)BIN#
BIN(n)Représentation binaire de n (entier signé sur 64 bits, lu en complément à deux si négatif).
SELECT BIN(5); -- '101'
SELECT BIN(-1); -- '1111111111111111111111111111111111111111111111111111111111111111' (64 uns)OCT#
OCT(n)Représentation octale de n, équivalente à CONV(n, 10, 8). Un argument texte est lu comme un préfixe entier décimal (lecture arrêtée au premier caractère non numérique, dépassement saturé) ; une chaîne vide rend NULL.
SELECT OCT(8); -- '10'CONV#
CONV(nombre, base_origine, base_cible)Convertit la représentation texte de nombre (lu dans base_origine) vers base_cible (bases de 2 à 36, valeur absolue). La lecture s'arrête au premier chiffre invalide pour la base d'origine ; les espaces de tête sont ignorés. NULL si l'une des bases est hors de 2–36.
Retour : texte.
SELECT CONV('FF', 16, 10); -- '255'
SELECT CONV(255, 10, 16); -- 'FF'MAKE_SET#
MAKE_SET(masque, chaine1, chaine2, ...)Liste séparée par des virgules des chaineN dont le bit N-1 de masque (entier) vaut 1 ; les bits au-delà du nombre de chaînes fournies sont ignorés. Une chaineN NULL est ignorée même si son bit est à 1. NULL si masque est NULL.
SELECT MAKE_SET(5, 'a', 'b', 'c'); -- 'a,c' (bits 0 et 2 à 1 : 5 = 0b101)EXPORT_SET#
EXPORT_SET(masque, on, off [, separateur [, nb_bits]])Pour chacun des nb_bits bits de masque (64 par défaut, borné à 0–64), rend on si le bit vaut 1, off sinon, du bit de poids faible vers le haut, joints par separateur (, par défaut).
SELECT EXPORT_SET(5, 'Y', 'N', ',', 4); -- 'Y,N,Y,N'SOUNDEX#
SOUNDEX(chaine)Code phonétique Soundex de chaine : la première lettre est recopiée (majuscule), puis un chiffre par consonne suivante selon la table Soundex classique (voyelles, H, W, Y ignorés sans séparer deux chiffres identiques), complété par des zéros jusqu'à 4 caractères. Chaîne vide si chaine ne contient aucune lettre.
SELECT SOUNDEX('Robert'); -- 'R163'
SELECT SOUNDEX('Rupert'); -- 'R163'NATURAL_SORT_KEY#
NATURAL_SORT_KEY(chaine)Produit une clé de texte telle qu'un tri lexicographique de ces clés équivaut à un « tri naturel » de chaine (les nombres inclus dans le texte triés par valeur, pas caractère par caractère : 'a2' avant 'a10'). Utile en ORDER BY NATURAL_SORT_KEY(colonne).
SELECT NATURAL_SORT_KEY('a2'), NATURAL_SORT_KEY('a10');
-- 'a02', 'a110' (la deuxième trie après la première)WEIGHT_STRING#
WEIGHT_STRING(chaine)
WEIGHT_STRING(chaine AS CHAR(n))
WEIGHT_STRING(chaine AS BINARY(n))Rend les octets de poids de tri de chaine selon son interclassement. En utf8mb4_unicode_ci : unités de 16 bits gros-boutistes (zéro, une ou plusieurs par caractère, 'ß' → 0FEA0FEA), AS CHAR(n) coupant à n unités puis complétant par 0209 ; en utf8mb4_bin : 3 octets par caractère (point de code), AS CHAR(n) complétant par 000020. En utf8mb4_general_ci (défaut) : un poids de 16 bits gros-boutiste par caractère, espaces finaux compris (HEX(WEIGHT_STRING('Crème')) rend 004300520045004D0045, comme pour 'creme' ; un caractère hors BMP pèse FFFD). AS CHAR(n) ramène d'abord le texte à n caractères (tronqué ou complété par des espaces), ce qui rend le même résultat pour deux chaînes égales selon = ; AS BINARY(n) ramène les octets bruts à n (tronqués ou complétés par des zéros). Une valeur numérique rend NULL (pas de poids de tri défini pour un nombre par cette fonction) ; une date ou une heure utilise les octets de son texte.
Retour : binaire (VARBINARY).
SELECT HEX(WEIGHT_STRING('Crème')); -- '004300520045004D0045'
SELECT HEX(WEIGHT_STRING('ab' AS CHAR(4))); -- '0041004200200020'
SELECT HEX(WEIGHT_STRING('ab' AS BINARY(4))); -- '61620000'LOAD_FILE#
LOAD_FILE(chemin)Contenu d'un fichier du serveur, en binaire. Le fichier doit se trouver dans le dossier autorisé par la variable serveur secure_file_priv, et l'utilisateur doit avoir le privilège FILE ; un chemin relatif part de ce dossier, et un chemin qui en sortirait (via ..) est refusé. Rend NULL, sans erreur, si aucun dossier n'est autorisé pour la session, si le fichier est absent, illisible, n'est pas un fichier ordinaire, ou dépasse max_allowed_packet.
Retour : binaire.
-- secure_file_priv désigne un dossier qui contient note.txt (texte « bonjour »)
SELECT LOAD_FILE('note.txt'); -- 'bonjour'
SELECT LOAD_FILE('absent.txt'); -- NULL
SELECT LOAD_FILE('../x'); -- NULL (hors du dossier autorisé)CONVERT (jeu de caractères)#
CONVERT(expr USING jeu_de_caracteres)
CAST(expr AS CHAR CHARACTER SET jeu_de_caracteres)Convertit expr vers le jeu de caractères nommé. Vers binary, rend les octets UTF-8 bruts du texte (type binaire) ; vers un autre jeu, rend un texte où les caractères non représentables dans ce jeu sont remplacés par ?. Cette forme de CONVERT (avec un jeu de caractères) est distincte de CONVERT(expr, type) qui effectue un changement de type SQL, décrit au chapitre 6. Types de données.
SELECT HEX(CONVERT('é' USING latin1)); -- 'E9'FORMAT_BYTES#
FORMAT_BYTES(octets)Écrit une taille en octets dans l'unité binaire la plus lisible : en dessous de 1024, N bytes (partie entière) ; au-delà, la valeur est divisée par 1024 tant qu'elle reste au moins égale à 1024 et s'écrit avec deux décimales suivie de KiB, MiB, GiB, TiB, PiB ou EiB. Une valeur négative garde son signe.
Retour : texte.
SELECT FORMAT_BYTES(512), FORMAT_BYTES(1536), FORMAT_BYTES(1073741824); -- '512 bytes', '1.50 KiB', '1.00 GiB'
SELECT FORMAT_BYTES(-2048); -- '-2.00 KiB'FORMAT_PICO_TIME#
FORMAT_PICO_TIME(picosecondes)Écrit une durée exprimée en picosecondes dans l'unité la plus lisible : en dessous de 1000, N ps ; au-delà, ns, us, ms, s (pas de 1000), puis min, h et d (pas de 60, 60 et 24), avec deux décimales. Une valeur négative garde son signe.
Retour : texte.
SELECT FORMAT_PICO_TIME(999), FORMAT_PICO_TIME(2500), FORMAT_PICO_TIME(1500000000); -- '999 ps', '2.50 ns', '1.50 ms'
SELECT FORMAT_PICO_TIME(90000000000000), FORMAT_PICO_TIME(86400000000000000); -- '1.50 min', '1.00 d'10.2 Fonctions numériques#
Les calculs sur DECIMAL restent exacts (arithmétique entière mise à l'échelle) ; une division, un modulo par zéro ou un domaine invalide (logarithme d'un nombre négatif, racine carrée d'un négatif...) rendent NULL plutôt que de lever une erreur.
Récapitulatif :
| Fonction | Signature |
|---|---|
| ABS | ABS(nombre) |
| SIGN | SIGN(nombre) |
| ROUND | ROUND(nombre [, decimales]) |
| TRUNCATE | TRUNCATE(nombre, decimales) <br> TRUNC(nombre, decimales) |
| FLOOR | FLOOR(nombre) |
| CEILING / CEIL | CEILING(nombre) |
| MOD | MOD(a, b) |
| POWER / POW | POWER(base, exposant) |
| SQRT | SQRT(nombre) |
| EXP | EXP(nombre) |
| LN | LN(nombre) |
| LOG | LOG(nombre) <br> LOG(base, nombre) |
| LOG10 | LOG10(nombre) |
| LOG2 | LOG2(nombre) |
| PI | PI() |
| RAND | RAND([graine]) |
| SIN, COS, TAN | SIN(angle_radians) <br> COS(angle_radians) <br> TAN(angle_radians) |
| COT | COT(angle_radians) |
| ASIN | ASIN(nombre) |
| ACOS | ACOS(nombre) |
| ATAN / ATAN2 | ATAN(nombre) <br> ATAN(y, x) <br> ATAN2(y, x) |
| DEGREES | DEGREES(angle_radians) |
| RADIANS | RADIANS(angle_degres) |
| GREATEST | GREATEST(expr1, expr2, ...) |
| LEAST | LEAST(expr1, expr2, ...) |
| CRC32 / CRC32C | CRC32(expr) <br> CRC32([graine,] expr) <br> CRC32C(expr) |
| BIT_COUNT | BIT_COUNT(n) |
| TO_NUMBER | TO_NUMBER(expr) |
ABS#
ABS(nombre)Valeur absolue. Un entier reste entier, un DECIMAL reste DECIMAL (même échelle), les autres deviennent DOUBLE. NULL en cas de dépassement (valeur minimale d'un BIGINT signé, dont l'opposé ne tient pas dans un BIGINT).
SELECT ABS(-5); -- 5
SELECT ABS(-5.25); -- 5.25SIGN#
SIGN(nombre)1 si nombre > 0, -1 si nombre < 0, 0 sinon.
Retour : BIGINT.
SELECT SIGN(-12.5), SIGN(0), SIGN(3); -- -1, 0, 1ROUND#
ROUND(nombre [, decimales])Arrondit nombre à decimales décimales (0 par défaut ; négatif pour arrondir à des dizaines, centaines...). Un entier reste entier (arrondi à des dizaines si decimales < 0) ; un BIGINT UNSIGNED arrondi à des dizaines par un nombre écrit rend un DECIMAL, l'arrondi pouvant dépasser 2⁶⁴ − 1 (ROUND(18446744073709551615, -1) = 18446744073709551620) ; un DECIMAL est arrondi au plus loin de zéro pour un demi (ROUND(0.5, 0) = 1) et le résultat garde le nombre de décimales demandé, complété de zéros si besoin (ROUND(2.567, 5) = 2.56700) ; un flottant (FLOAT/DOUBLE) est arrondi au plus proche pair (mode IEEE 754 par défaut : ROUND(2.5e0) = 2, ROUND(1.5e0) = 2, ROUND(0.5e0) = 0), comme pour tout calcul en virgule flottante.
SELECT ROUND(1250, -2); -- 1300 (entier)
SELECT ROUND(2.5); -- 3 (DECIMAL littéral : arrondi au plus loin de zéro)
SELECT ROUND(1.005, 2); -- 1.01 (DECIMAL exact)
SELECT ROUND(2.5e0), ROUND(1.5e0), ROUND(0.5e0); -- 2.0, 2.0, 0.0 (DOUBLE : au plus proche pair)TRUNCATE#
TRUNCATE(nombre, decimales)Tronque nombre à decimales décimales sans arrondir (troncature vers zéro). decimales est obligatoire, contrairement à ROUND. TRUNC(nombre, decimales) en est un synonyme, aux mêmes règles (décimales négatives, NULL, deux arguments).
SELECT TRUNCATE(1.999, 2); -- 1.99
SELECT TRUNCATE(1999, -2); -- 1900
SELECT TRUNC(1.999, 2); -- 1.99FLOOR#
FLOOR(nombre)Plus grand entier inférieur ou égal à nombre. NULL si hors de la plage d'un BIGINT signé.
Retour : BIGINT.
SELECT FLOOR(1.9); -- 1
SELECT FLOOR(-1.1); -- -2CEILING / CEIL#
CEILING(nombre)Plus petit entier supérieur ou égal à nombre. CEIL est un alias strict.
SELECT CEILING(1.1); -- 2
SELECT CEILING(-1.9); -- -1MOD#
MOD(a, b)Reste de la division entière de a par b (même signe que a, comme l'opérateur %). NULL si b vaut 0. Un entier divisé par un entier rend un entier ; sinon le calcul passe par une division flottante mais le résultat garde la représentation numérique du premier argument (entier, DECIMAL ou DOUBLE).
SELECT MOD(10, 3); -- 1
SELECT MOD(-10, 3); -- -1
SELECT MOD(10, 0); -- NULLPOWER / POW#
POWER(base, exposant)base élevé à la puissance exposant. POW est un alias strict.
Retour : DOUBLE.
SELECT POWER(2, 10), POW(2, -1); -- 1024.0, 0.5SQRT#
SQRT(nombre)Racine carrée. NULL si nombre < 0.
SELECT SQRT(16); -- 4.0
SELECT SQRT(-1); -- NULLEXP#
EXP(nombre)e élevé à la puissance nombre.
SELECT EXP(1); -- 2.718281828459045LN#
LN(nombre)Logarithme népérien. NULL si nombre <= 0.
SELECT LN(1), LN(EXP(2)), LN(0); -- 0.0, 2.0, NULLLOG#
LOG(nombre)
LOG(base, nombre)Sans base, logarithme népérien (identique à LN). Avec base, logarithme de nombre en base base. NULL si nombre <= 0, base <= 0 ou base = 1.
SELECT LOG(2, 8); -- 3.0LOG10#
LOG10(nombre)Logarithme décimal. NULL si nombre <= 0.
SELECT LOG10(1000), LOG10(-1); -- 3.0, NULLLOG2#
LOG2(nombre)Logarithme en base 2. NULL si nombre <= 0.
SELECT LOG2(8); -- 3.0PI#
PI()La constante π (3.141592653589793), sans argument.
Retour : DOUBLE. Fonction constante (évaluée une fois par instruction).
SELECT PI(), ROUND(PI(), 4); -- 3.141592653589793, 3.1416RAND#
RAND([graine])Nombre flottant pseudo-aléatoire dans [0, 1). Sans argument, une nouvelle valeur à chaque appel. Avec graine (un entier constant ou une expression), le générateur est réamorcé avec cette graine : deux appels avec la même graine rendent la même valeur. graine égale à NULL équivaut à 0.
SELECT RAND(); -- par exemple 0.02946782614786525 (change à chaque appel)
SELECT RAND(42), RAND(42); -- 0.5265574090027738, 0.5265574090027738SIN, COS, TAN#
SIN(angle_radians)
COS(angle_radians)
TAN(angle_radians)Fonctions trigonométriques usuelles, argument en radians.
Retour : DOUBLE.
SELECT SIN(PI()/2), COS(0), TAN(PI()/4); -- 1.0, 1.0, 0.9999999999999999COT#
COT(angle_radians)Cotangente (1 / TAN(angle_radians)). NULL si TAN(angle_radians) = 0.
SELECT COT(1), COT(0); -- 0.6420926159343308, NULLASIN#
ASIN(nombre)Arc sinus, en radians. NULL si nombre hors de [-1, 1].
SELECT ASIN(1), ASIN(2); -- 1.5707963267948966, NULLACOS#
ACOS(nombre)Arc cosinus, en radians. NULL si nombre hors de [-1, 1].
SELECT ACOS(1), ACOS(0); -- 0.0, 1.5707963267948966ATAN / ATAN2#
ATAN(nombre)
ATAN(y, x)
ATAN2(y, x)ATAN(nombre) : arc tangente en radians. ATAN(y, x) (ou ATAN2(y, x)) : angle du point (x, y), tenant compte du quadrant.
SELECT ATAN(1), ATAN(1, -1), ATAN2(-1, -1); -- 0.7853981633974483, 2.356194490192345, -2.356194490192345DEGREES#
DEGREES(angle_radians)Convertit des radians en degrés.
SELECT DEGREES(PI()); -- 180.0RADIANS#
RADIANS(angle_degres)Convertit des degrés en radians.
SELECT RADIANS(180); -- 3.141592653589793GREATEST#
GREATEST(expr1, expr2, ...)La plus grande des expressions, comparées selon un ordre commun déduit de leurs types (voir le tableau de typage de COALESCE en 10.4). NULL si l'une des expressions est NULL.
SELECT GREATEST(3, 7, 2); -- 7LEAST#
LEAST(expr1, expr2, ...)La plus petite des expressions, mêmes règles que GREATEST.
SELECT LEAST(3, 7, 2); -- 2CRC32 / CRC32C#
CRC32(expr)
CRC32([graine,] expr)
CRC32C(expr)
CRC32C([graine,] expr)Somme de contrôle CRC-32 (polynôme standard pour CRC32, Castagnoli pour CRC32C) des octets de expr (octets bruts pour une valeur binaire, texte UTF-8 sinon). Avec une graine (résultat d'un appel précédent), enchaîne le calcul : CRC32C(CRC32C('a'), 'b') équivaut à CRC32C('ab').
Retour : BIGINT (valeur non signée sur 32 bits, représentée comme un entier positif).
SELECT CRC32('MIRAJ'), CRC32C('MIRAJ'); -- 2416857158, 3509818374
SELECT CRC32C(CRC32C('a'), 'b') = CRC32C('ab'); -- 1BIT_COUNT#
BIT_COUNT(n)Nombre de bits à 1 de l'entier n sur 64 bits (BIT_COUNT(-1) : 64) ; NULL si n est NULL.
Retour : BIGINT.
SELECT BIT_COUNT(7); -- 3TO_NUMBER#
TO_NUMBER(expr)Nombre lu dans le texte expr, comme CAST(expr AS DECIMAL) sans perte de décimales ; un nombre est rendu tel quel. Un texte qui n'est pas entièrement un nombre vaut son préfixe numérique (0 s'il n'y en a pas), avec l'avertissement 1292 (Truncated incorrect DECIMAL value).
Retour : BIGINT pour un entier constant, DECIMAL (échelle du texte) pour un décimal constant, DOUBLE sinon.
SELECT TO_NUMBER('123.45'), TO_NUMBER('42'), TO_NUMBER(7.5); -- 123.45, 42, 7.5
SELECT TO_NUMBER('12abc'); -- 12 (avertissement 1292)10.3 Fonctions de date et heure#
Les fonctions ci-dessous acceptent une valeur DATE, TIME, DATETIME ou TIMESTAMP, ou un texte qui se lit comme telle ('2026-09-13', '2026-09-13 08:09:10.5'). Les fonctions de l'heure courante acceptent une précision fractionnaire facultative de 0 à 6 chiffres (NOW(3), CURTIME(6)).
Récapitulatif :
| Fonction | Signature |
|---|---|
| NOW / CURRENT_TIMESTAMP / LOCALTIME / LOCALTIMESTAMP | NOW([precision]) |
| SYSDATE | SYSDATE([precision]) |
| CURDATE / CURRENT_DATE | CURDATE() |
| CURTIME / CURRENT_TIME | CURTIME([precision]) |
| UTC_TIMESTAMP, UTC_DATE, UTC_TIME | UTC_TIMESTAMP([precision]) <br> UTC_DATE() <br> UTC_TIME([precision]) |
| DATE | DATE(expr) |
| TIME | TIME(expr) |
| TIMESTAMP | TIMESTAMP(expr) <br> TIMESTAMP(date_expr, heure_expr) |
| YEAR | YEAR(expr) |
| MONTH | MONTH(expr) |
| DAY / DAYOFMONTH | DAY(expr) |
| HOUR | HOUR(expr) |
| MINUTE | MINUTE(expr) |
| SECOND | SECOND(expr) |
| MICROSECOND | MICROSECOND(expr) |
| DAYOFWEEK | DAYOFWEEK(expr) |
| WEEKDAY | WEEKDAY(expr) |
| DAYOFYEAR | DAYOFYEAR(expr) |
| QUARTER | QUARTER(expr) |
| WEEK | WEEK(expr [, mode]) |
| WEEKOFYEAR | WEEKOFYEAR(expr) |
| YEARWEEK | YEARWEEK(expr [, mode]) |
| DAYNAME | DAYNAME(expr) |
| MONTHNAME | MONTHNAME(expr) |
| LAST_DAY | LAST_DAY(expr) |
| DATE_FORMAT / TIME_FORMAT | DATE_FORMAT(expr, format) |
| TO_CHAR | TO_CHAR(expr [, modele]) |
| STR_TO_DATE | STR_TO_DATE(chaine, format) |
| DATE_ADD / ADDDATE | DATE_ADD(expr, INTERVAL n unite) |
| DATE_SUB / SUBDATE | DATE_SUB(expr, INTERVAL n unite) |
| ADD_MONTHS | ADD_MONTHS(expr, n) |
| MONTHS_BETWEEN | MONTHS_BETWEEN(expr1, expr2) |
| TIMESTAMPADD | TIMESTAMPADD(unite, n, expr) |
| DATEDIFF | DATEDIFF(expr1, expr2) |
| TIMEDIFF | TIMEDIFF(expr1, expr2) |
| TIMESTAMPDIFF | TIMESTAMPDIFF(unite, expr1, expr2) |
| ADDTIME | ADDTIME(expr, duree) |
| SUBTIME | SUBTIME(expr, duree) |
| UNIX_TIMESTAMP | UNIX_TIMESTAMP() <br> UNIX_TIMESTAMP(expr) |
| FROM_UNIXTIME | FROM_UNIXTIME(secondes [, format]) |
| TO_DAYS | TO_DAYS(expr) |
| FROM_DAYS | FROM_DAYS(n) |
| MAKEDATE | MAKEDATE(annee, jour_de_lannee) |
| MAKETIME | MAKETIME(heure, minute, seconde) |
| TIME_TO_SEC | TIME_TO_SEC(expr) |
| SEC_TO_TIME | SEC_TO_TIME(secondes) |
| EXTRACT | EXTRACT(unite FROM expr) |
| TO_SECONDS | TO_SECONDS(expr) |
| PERIOD_ADD | PERIOD_ADD(periode, n) |
| PERIOD_DIFF | PERIOD_DIFF(periode1, periode2) |
| GET_FORMAT | GET_FORMAT({DATE | TIME | DATETIME | TIMESTAMP}, {'EUR' | 'USA' | 'JIS' | 'ISO' | 'INTERNAL'}) |
| CONVERT_TZ | CONVERT_TZ(expr, fuseau_origine, fuseau_cible) |
NOW / CURRENT_TIMESTAMP / LOCALTIME / LOCALTIMESTAMP#
NOW([precision])Date et heure courantes dans le fuseau de la session (variable time_zone, voir Fuseau horaire de la session), figées au début de l'instruction : tous les appels à NOW() dans une même instruction (y compris pour plusieurs lignes) rendent la même valeur. precision (0 à 6) fixe le nombre de chiffres des fractions de seconde. CURRENT_TIMESTAMP, LOCALTIME et LOCALTIMESTAMP sont des alias stricts, qui s'écrivent aussi sans parenthèses.
Retour : DATETIME.
SELECT NOW(); -- '2026-10-19 03:25:54' (instant de l'exécution)
SELECT NOW(3); -- '2026-10-19 03:27:45.989'
SELECT CURRENT_TIMESTAMP, LOCALTIMESTAMP() = NOW(); -- '2026-10-19 03:27:45', 1SYSDATE#
SYSDATE()Comme NOW(), mais lit l'horloge à chaque appel (non figée pour l'instruction) : deux appels à SYSDATE() dans la même instruction peuvent différer.
SELECT SYSDATE() >= NOW(), SYSDATE(2); -- 1, '2026-10-19 03:27:45.98'CURDATE / CURRENT_DATE#
CURDATE()Date courante (sans heure), figée pour l'instruction. CURRENT_DATE est un alias strict (avec ou sans parenthèses).
Retour : DATE.
SELECT CURDATE(), CURRENT_DATE; -- '2026-10-19', '2026-10-19'CURTIME / CURRENT_TIME#
CURTIME([precision])Heure courante (sans date), figée pour l'instruction. CURRENT_TIME est un alias strict (avec ou sans parenthèses).
Retour : TIME.
SELECT CURTIME(), CURTIME(6); -- '03:27:45', '03:27:45.989207'UTC_TIMESTAMP, UTC_DATE, UTC_TIME#
UTC_TIMESTAMP([precision])
UTC_DATE()
UTC_TIME([precision])Équivalents de NOW(), CURDATE() et CURTIME() en heure UTC plutôt que locale, tous figés pour l'instruction.
-- session dans le fuseau Europe/Paris (heure d'été)
SELECT NOW(), UTC_TIMESTAMP(), UTC_DATE(), UTC_TIME();
-- '2026-10-19 03:27:45', '2026-10-19 02:27:45', '2026-10-19', '02:27:45'DATE#
DATE(expr)Partie date d'une expression date/heure (heure mise à zéro).
Retour : DATE.
SELECT DATE('2026-09-13 08:09:10'); -- '2026-09-13'TIME#
TIME(expr)Partie heure d'une expression date/heure.
Retour : TIME.
SELECT TIME('2026-09-13 08:09:10'); -- '08:09:10'TIMESTAMP#
TIMESTAMP(expr)
TIMESTAMP(date_expr, heure_expr)Avec un argument, convertit expr en DATETIME. Avec deux arguments, ajoute la durée heure_expr à date_expr (le résultat peut passer au jour suivant).
Retour : DATETIME.
SELECT TIMESTAMP('2026-09-13'); -- '2026-09-13 00:00:00'
SELECT TIMESTAMP('2026-09-13', '08:30:00'); -- '2026-09-13 08:30:00'
SELECT TIMESTAMP('2026-09-13 23:00:00', '02:00:00'); -- '2026-09-14 01:00:00'YEAR#
YEAR(expr)Année (BIGINT).
SELECT YEAR('2026-09-13'); -- 2026MONTH#
MONTH(expr)Mois, de 1 à 12 (BIGINT).
SELECT MONTH('2026-09-13'); -- 9DAY / DAYOFMONTH#
DAY(expr)Jour du mois, de 1 à 31 (BIGINT). DAYOFMONTH est un alias strict.
SELECT DAY('2026-09-13'), DAYOFMONTH('2026-09-13'); -- 13, 13HOUR#
HOUR(expr)Heure, de 0 à 23 pour une date/heure ; pour une valeur TIME, peut dépasser 23 (une durée TIME peut représenter plus de 24 heures), et une durée négative donne son heure sans le signe. Un texte est lu d'abord comme une durée [-]H:MM:SS, puis, s'il n'en est pas une, comme une date/heure.
SELECT HOUR('2026-09-13 08:09:10'), HOUR(TIME '125:30:00'); -- 8, 125
SELECT HOUR('125:30:00'), HOUR('-125:30:00'); -- 125, 125MINUTE#
MINUTE(expr)Minute, de 0 à 59. Un texte est lu comme pour HOUR : d'abord comme une durée, puis comme une date/heure.
SELECT MINUTE('2026-09-13 08:09:10'), MINUTE('125:30:15'); -- 9, 30SECOND#
SECOND(expr)Seconde, de 0 à 59. Un texte est lu comme pour HOUR.
SELECT SECOND('2026-09-13 08:09:10'), SECOND('125:30:15'); -- 10, 15MICROSECOND#
MICROSECOND(expr)Microsecondes de la partie fractionnaire (0 à 999999).
SELECT MICROSECOND('2026-09-13 08:09:10.123456'), MICROSECOND('10:00:00.5'); -- 123456, 500000DAYOFWEEK#
DAYOFWEEK(expr)Jour de la semaine selon la convention usuelle : 1 = dimanche, ..., 7 = samedi.
SELECT DAYOFWEEK('2026-09-13'), DAYOFWEEK('2026-09-19'); -- 1, 7 (dimanche, samedi)WEEKDAY#
WEEKDAY(expr)Jour de la semaine selon la convention ISO : 0 = lundi, ..., 6 = dimanche.
SELECT DAYOFWEEK('2026-09-13'), WEEKDAY('2026-09-13'); -- 1, 6 (dimanche)DAYOFYEAR#
DAYOFYEAR(expr)Rang du jour dans l'année (1 à 366).
SELECT DAYOFYEAR('2026-09-13'); -- 256QUARTER#
QUARTER(expr)Trimestre de l'année, de 1 à 4.
SELECT QUARTER('2026-09-13'); -- 3WEEK#
WEEK(expr [, mode])Numéro de semaine dans l'année (0 par défaut sans mode). mode (0 à 7) combine trois choix indépendants par ses bits :
| Bit | Valeur 0 | Valeur 1 |
|---|---|---|
1 (+1) | La semaine commence le dimanche | La semaine commence le lundi |
2 (+2) | Semaines numérotées 0 à 53 (la semaine 0 précède la première semaine complète) | Semaines numérotées 1 à 53 (la semaine 0 de l'année devient la 53 de l'année précédente) |
4 (+4) | La semaine 1 est la première comptant au moins 4 jours dans l'année | La semaine 1 est la première contenant le jour de début de semaine (1er janvier) |
SELECT WEEK('2026-01-01', 0); -- 0 (le 1er janvier 2026 est un jeudi, avant le premier dimanche)
SELECT WEEK('2026-01-01', 1); -- 1
SELECT WEEK('2026-09-13'); -- 37WEEKOFYEAR#
WEEKOFYEAR(expr)Équivalent à WEEK(expr, 3) (semaines ISO 8601 : lundi, numérotées 1 à 53, semaine 1 = celle contenant le premier jeudi de l'année).
SELECT WEEKOFYEAR('2026-09-13'); -- 37YEARWEEK#
YEARWEEK(expr [, mode])Année et semaine combinées en un seul entier AAAASS (mode par défaut 0, mêmes bits que WEEK, avec le bit « semaines 1–53 » toujours actif).
SELECT YEARWEEK('2026-09-13'); -- 202637DAYNAME#
DAYNAME(expr)Nom complet du jour de la semaine, en anglais ('Sunday', 'Monday', ...).
SELECT DAYNAME('2026-09-13'); -- 'Sunday'MONTHNAME#
MONTHNAME(expr)Nom complet du mois, en anglais ('January', ...).
SELECT MONTHNAME('2026-09-13'); -- 'September'LAST_DAY#
LAST_DAY(expr)Date du dernier jour du mois de expr.
Retour : DATE.
SELECT LAST_DAY('2026-02-10'); -- '2026-02-28'DATE_FORMAT / TIME_FORMAT#
DATE_FORMAT(expr, format)Met expr en forme selon format, une chaîne avec des spécificateurs %X :
| Spéc. | Signification | Spéc. | Signification |
|---|---|---|---|
%Y | Année sur 4 chiffres | %y | Année sur 2 chiffres |
%m | Mois sur 2 chiffres | %c | Mois sans zéro de tête |
%d | Jour sur 2 chiffres | %e | Jour sans zéro de tête |
%H | Heure 24h sur 2 chiffres | %k | Heure 24h sans zéro |
%h, %I | Heure 12h sur 2 chiffres | %l | Heure 12h sans zéro |
%i | Minute sur 2 chiffres | %s, %S | Seconde sur 2 chiffres |
%f | Microsecondes sur 6 chiffres | %p | AM/PM |
%r | Heure 12h complète (hh:mm:ss AM/PM) | %T | Heure 24h complète (hh:mm:ss) |
%W | Nom complet du jour | %a | Nom abrégé du jour (3 lettres) |
%M | Nom complet du mois | %b | Nom abrégé du mois (3 lettres) |
%j | Jour de l'année sur 3 chiffres | %w | Jour de la semaine (0 = dimanche) |
%D | Jour du mois avec suffixe ordinal (1st, 2nd...) | %U,%u,%V,%v | Semaine de l'année (modes 0,1,2,3) |
%X,%x | Année de la semaine (modes 2,3) | %% | Le caractère % |
TIME_FORMAT est un alias strict (utile en documentation avec un format sans partie date).
Retour : texte.
SELECT DATE_FORMAT('2026-09-13 08:09:10', '%W %d %M %Y à %H:%i');
-- 'Sunday 13 September 2026 à 08:09'
SELECT DATE_FORMAT('2026-09-01', '%D %b %y, %a %j'); -- '1st Sep 26, Tue 244'
SELECT TIME_FORMAT('08:09:10', '%Hh%i'); -- '08h09'TO_CHAR#
TO_CHAR(expr [, modele])Met en forme une date, une heure ou une date-heure (ou un texte lu comme une date-heure) selon un modèle à la Oracle. Sans modele, 'YYYY-MM-DD HH24:MI:SS' est employé quel que soit le type de expr (une date s'écrit donc avec 00:00:00, une heure avec 0000-00-00). Les champs se lisent sans égard à la casse :
| Champ | Signification | Champ | Signification |
|---|---|---|---|
YYYY, RRRR | Année sur 4 chiffres | YYY, YY / RR, Y | 3, 2 ou 1 derniers chiffres de l'année |
MM | Mois sur 2 chiffres | MON | Nom abrégé du mois (Jan) |
MONTH | Nom complet du mois, complété d'espaces jusqu'à 9 caractères | DD | Jour sur 2 chiffres |
DY | Nom abrégé du jour (Mon) | DAY | Nom complet du jour, complété d'espaces jusqu'à 9 caractères |
HH, HH12 | Heure sur 12 heures, 2 chiffres | HH24 | Heure sur 24 heures, 2 chiffres |
MI | Minute sur 2 chiffres | SS | Seconde sur 2 chiffres |
AM, PM | AM ou PM selon l'heure | A.M., P.M. | A.M. ou P.M. |
AD, BC | AD (BC pour l'an 0) | A.D., B.C. | A.D. (B.C. pour l'an 0) |
La ponctuation et les espaces sont recopiés ; un texte entre guillemets doubles l'est aussi, sans ses guillemets ('YYYY"abc"MM'). Un | seul sépare deux champs sans rien écrire ; de plusieurs | à la suite, le premier seul est omis. Les noms de mois et de jours sont en anglais et s'écrivent January, Jan, Monday, Mon quelle que soit la casse du modèle. Pour une heure (TIME), l'année, le mois et le jour valent zéro (MON, DY : 00) et HH24 peut dépasser 23.
NULL si un argument est NULL, si le modèle est vide ou si un texte ne se lit pas comme une date (avertissement 1292). Toute autre lettre, un chiffre ou un caractère non ASCII hors guillemets est refusé : erreur 3047 (Invalid argument error: date format not recognized at … in function to_char.) pour un modèle constant, NULL et avertissement 3047 pour un modèle lu dans une colonne. Un nombre en premier argument est refusé (3047) : TO_CHAR ne met pas en forme les nombres (voir FORMAT). Le modèle compte au plus 144 octets.
Retour : texte sous l'interclassement de la connexion (@@collation_connection), quel que soit celui d'un premier argument texte ; avec un modèle constant, sa longueur maximale est connue (VARCHAR(10) pour 'YYYY-MM-DD', 27 caractères comptés pour MONTH et DAY).
SELECT TO_CHAR('2026-09-13 08:09:10', 'DD/MM/YYYY HH24:MI'); -- '13/09/2026 08:09'
SELECT TO_CHAR('2026-09-13 20:09:10', 'DY DD MON YYYY, HH:MI PM'); -- 'Sun 13 Sep 2026, 08:09 PM'
SELECT TO_CHAR('2026-09-13', 'YYYY"-T"MM'); -- '2026-T09'
SELECT TO_CHAR(DATE'2026-09-13'); -- '2026-09-13 00:00:00'En langage PostgreSQL, to_char est la fonction de PostgreSQL (modèles de dates et de nombres, voir le chapitre 30).
STR_TO_DATE#
STR_TO_DATE(chaine, format)Analyse chaine selon format (mêmes spécificateurs que DATE_FORMAT, plus %p et %T en lecture) et rend la date/heure correspondante. NULL si chaine ne correspond pas exactement au format ou décrit une date invalide (par ex. '2026-02-30'). Le type de retour (DATE, TIME ou DATETIME) est déduit des spécificateurs présents dans format quand celui-ci est une constante.
SELECT STR_TO_DATE('13/09/2026', '%d/%m/%Y'); -- '2026-09-13' (DATE)
SELECT STR_TO_DATE('13/09/2026 08:30', '%d/%m/%Y %H:%i'); -- '2026-09-13 08:30:00' (DATETIME)
SELECT STR_TO_DATE('08:30 PM', '%h:%i %p'); -- '20:30:00' (TIME)
SELECT STR_TO_DATE('31/02/2026', '%d/%m/%Y'); -- NULL (jour invalide)DATE_ADD / ADDDATE#
DATE_ADD(expr, INTERVAL n unite)Ajoute n unités unite à expr. Unités simples : YEAR, QUARTER, MONTH, WEEK, DAY, HOUR, MINUTE, SECOND, MICROSECOND. Unités composites acceptées avec un intervalle textuel (INTERVAL '1:30' HOUR_MINUTE, INTERVAL '2-3' YEAR_MONTH, etc.) : YEAR_MONTH, DAY_HOUR, DAY_MINUTE, DAY_SECOND, DAY_MICROSECOND, HOUR_MINUTE, HOUR_SECOND, HOUR_MICROSECOND, MINUTE_SECOND, MINUTE_MICROSECOND, SECOND_MICROSECOND. Un ajout de mois qui dépasse le dernier jour du mois cible le ramène à ce dernier jour ('2026-01-31' + INTERVAL 1 MONTH = '2026-02-28'). NULL si le résultat sort de la plage 0001-01-01 à 9999-12-31, avec l'avertissement 1441 (Datetime function: datetime field overflow). ADDDATE est un alias strict, acceptant aussi la forme à trois arguments ADDDATE(expr, n, 'unite').
Retour : DATE si expr est une date et l'unité vaut un jour ou plus, TIME si expr est une heure, DATETIME sinon.
SELECT DATE_ADD('2026-01-31', INTERVAL 1 MONTH); -- '2026-02-28'
SELECT DATE_ADD('2026-01-01 10:00', INTERVAL '1:30' HOUR_MINUTE); -- '2026-01-01 11:30:00'
SELECT ADDDATE('2026-09-13', 10), ADDDATE('2026-09-13', INTERVAL 2 WEEK); -- '2026-09-23', '2026-09-27'DATE_SUB / SUBDATE#
DATE_SUB(expr, INTERVAL n unite)Comme DATE_ADD, mais soustrait. SUBDATE est un alias strict, qui accepte aussi un nombre de jours en second argument.
SELECT DATE_SUB('2026-03-01', INTERVAL 1 DAY); -- '2026-02-28'
SELECT SUBDATE('2026-09-13', 10); -- '2026-09-03'ADD_MONTHS#
ADD_MONTHS(expr, n)Ajoute n mois à expr (les retranche si n est négatif) : équivalent de DATE_ADD(expr, INTERVAL n MONTH). n est arrondi à l'entier. Si le jour n'existe pas dans le mois d'arrivée, le dernier jour de ce mois est retenu ; le dernier jour d'un mois court n'est pas reporté sur le dernier jour du mois d'arrivée (ADD_MONTHS('2024-02-29', 1) = '2024-03-29'). NULL si un argument est NULL, si le résultat sort des années 1 à 9999 (avertissement 1441, comme DATE_ADD) ou si un texte ne se lit pas comme une date (avertissement 1292).
Retour : comme DATE_ADD avec une unité MONTH : DATE pour une date (ou une chaîne constante sans heure), DATETIME sinon (heure et fraction de seconde gardées).
SELECT ADD_MONTHS('2024-01-31', 1); -- '2024-02-29'
SELECT ADD_MONTHS('2024-03-31', -1); -- '2024-02-29'
SELECT ADD_MONTHS('2024-01-31 10:20:30', 13); -- '2025-02-28 10:20:30'MONTHS_BETWEEN#
MONTHS_BETWEEN(expr1, expr2)Nombre de mois de expr2 à expr1 (expr1 - expr2), négatif si expr1 précède expr2. Le résultat est entier quand les deux dates tombent le même jour du mois ou sont toutes deux des derniers jours de mois ; sinon la partie fractionnaire compte la différence de jours (et d'heures) sur la base d'un mois de 31 jours.
Retour : DOUBLE.
SELECT MONTHS_BETWEEN('2026-09-13', '2026-06-13'); -- 3.0
SELECT MONTHS_BETWEEN('2026-03-31', '2026-02-28'); -- 1.0 (deux fins de mois)
SELECT MONTHS_BETWEEN('2026-02-15', '2026-01-01'); -- 1.4516129032258065
SELECT MONTHS_BETWEEN('2024-01-01', '2024-03-15'); -- -2.4516129032258065TIMESTAMPADD#
TIMESTAMPADD(unite, n, expr)Ajoute n unités unite (mêmes unités simples que DATE_ADD) à expr ; ordre des arguments différent de DATE_ADD.
Retour : DATETIME.
SELECT TIMESTAMPADD(DAY, 7, '2026-09-13'); -- '2026-09-20 00:00:00'DATEDIFF#
DATEDIFF(expr1, expr2)Différence en nombre entier de jours entre les parties date de expr1 et expr2 (expr1 - expr2), sans tenir compte de l'heure.
Retour : BIGINT.
SELECT DATEDIFF('2026-09-20', '2026-09-13'); -- 7TIMEDIFF#
TIMEDIFF(expr1, expr2)Différence expr1 - expr2 sous forme de durée (négative si expr1 précède expr2) ; les deux arguments doivent être du même genre (deux dates-heures ou deux heures).
Retour : TIME.
SELECT TIMEDIFF('2026-09-13 10:00:00', '2026-09-12 08:30:00'); -- '25:30:00'
SELECT TIMEDIFF('08:00', '09:30'); -- '-01:30:00'TIMESTAMPDIFF#
TIMESTAMPDIFF(unite, expr1, expr2)Différence entière expr2 - expr1 exprimée en unite (YEAR, QUARTER, MONTH, WEEK, DAY, HOUR, MINUTE, SECOND, MICROSECOND). Pour YEAR, QUARTER et MONTH, le calcul est calendaire exact : il compte les mois pleins réellement écoulés (en tenant compte du jour et de l'heure), pas une approximation par division d'un nombre de jours moyen. Par exemple, entre deux 15 janvier consécutifs, la différence en années vaut toujours exactement 1, quelle que soit la présence d'une année bissextile entre les deux — un calcul par 365.25 jours donnerait parfois 0 à tort.
Retour : BIGINT.
SELECT TIMESTAMPDIFF(MONTH, '2026-01-15', '2026-04-10'); -- 2 (pas encore 3 mois pleins)
SELECT TIMESTAMPDIFF(YEAR, '2001-01-01', '2002-01-01'); -- 1 (exact, calendaire)ADDTIME#
ADDTIME(expr, duree)Ajoute duree (une heure, ou un texte d'intervalle de temps) à expr.
Retour : DATETIME si expr porte une date, TIME sinon.
SELECT ADDTIME('2026-09-13 23:00:00', '02:30:00'); -- '2026-09-14 01:30:00'
SELECT ADDTIME('10:00:00', '1:15:30'); -- '11:15:30'SUBTIME#
SUBTIME(expr, duree)Comme ADDTIME, mais soustrait.
SELECT SUBTIME('2026-09-13 01:00:00', '02:00:00'); -- '2026-09-12 23:00:00'UNIX_TIMESTAMP#
UNIX_TIMESTAMP()
UNIX_TIMESTAMP(expr)Sans argument, secondes écoulées depuis l'epoch Unix (1er janvier 1970 UTC) jusqu'à l'instant de début de l'instruction. Avec expr (heure locale du fuseau de la session, time_zone), secondes Unix correspondantes.
Retour : BIGINT.
SET time_zone = '+00:00';
SELECT UNIX_TIMESTAMP('1970-01-02 00:00:00'), UNIX_TIMESTAMP('2026-09-13 00:00:00'); -- 86400, 1789257600FROM_UNIXTIME#
FROM_UNIXTIME(secondes [, format])Date-heure, dans le fuseau de la session (time_zone), correspondant à secondes (secondes Unix, fractions acceptées à la milliseconde près). Avec format, rend directement le texte mis en forme (comme DATE_FORMAT).
Retour : DATETIME, ou texte si format est fourni.
SET time_zone = '+00:00';
SELECT FROM_UNIXTIME(1767323045); -- '2026-01-02 03:04:05'
SELECT FROM_UNIXTIME(1767323045.5); -- '2026-01-02 03:04:05.5'
SELECT FROM_UNIXTIME(1789257600, '%d/%m/%Y'); -- '13/09/2026'TO_DAYS#
TO_DAYS(expr)Nombre de jours écoulés depuis le jour 0 du calendrier grégorien proleptique, pour la partie date de expr.
Retour : BIGINT.
SELECT TO_DAYS('2026-09-13'); -- 740237FROM_DAYS#
FROM_DAYS(n)Date correspondant au nombre de jours n depuis le jour 0 (inverse de TO_DAYS). Ne tient pas compte du calendrier grégorien avant son adoption ; à réserver aux calculs de différences entre dates plutôt qu'à des dates historiques réelles.
Retour : DATE.
SELECT FROM_DAYS(740237); -- '2026-09-13'MAKEDATE#
MAKEDATE(annee, jour_de_lannee)Date du jour_de_lannee-ième jour de annee (le 1er janvier = jour 1). NULL si jour_de_lannee < 1.
SELECT MAKEDATE(2026, 1); -- '2026-01-01'
SELECT MAKEDATE(2026, 60); -- '2026-03-01'MAKETIME#
MAKETIME(heure, minute, seconde)Construit une heure à partir de ses composantes (seconde accepte une fraction).
Retour : TIME.
SELECT MAKETIME(8, 30, 15); -- '08:30:15'TIME_TO_SEC#
TIME_TO_SEC(expr)Nombre entier de secondes correspondant à la partie heure de expr (ou à expr directement s'il s'agit déjà d'une heure).
Retour : BIGINT.
SELECT TIME_TO_SEC('01:01:01'), TIME_TO_SEC('2026-09-13 10:00:00'); -- 3661, 36000SEC_TO_TIME#
SEC_TO_TIME(secondes)Heure correspondant à secondes (fractions de seconde acceptées).
Retour : TIME.
SELECT SEC_TO_TIME(3661); -- '01:01:01'EXTRACT#
EXTRACT(unite FROM expr)Extrait un champ de expr : YEAR, QUARTER, MONTH, WEEK, DAY, HOUR, MINUTE, SECOND, MICROSECOND, ou une unité composite (YEAR_MONTH, DAY_HOUR, DAY_MINUTE, DAY_SECOND, DAY_MICROSECOND, HOUR_MINUTE, HOUR_SECOND, HOUR_MICROSECOND, MINUTE_SECOND, MINUTE_MICROSECOND, SECOND_MICROSECOND) qui combine plusieurs champs en un seul entier (par ex. YEAR_MONTH donne AAAAMM).
Retour : BIGINT.
SELECT EXTRACT(YEAR_MONTH FROM '2026-09-13'); -- 202609
SELECT EXTRACT(DAY_MINUTE FROM '2026-09-13 08:09:10'); -- 130809
SELECT EXTRACT(WEEK FROM '2026-09-13'); -- 37TO_SECONDS#
TO_SECONDS(expr)Nombre de secondes écoulées depuis le jour 0 de l'an 0 jusqu'à expr (combine TO_DAYS et l'heure du jour).
Retour : BIGINT.
SELECT TO_SECONDS('2026-09-13 00:00:01'); -- 63956476801PERIOD_ADD#
PERIOD_ADD(periode, n)Ajoute n mois à periode, une période au format AAMM ou AAAAMM (les années à deux chiffres inférieures à 70 sont lues comme 20xx, sinon 19xx). 0 reste 0 quel que soit n.
Retour : BIGINT au format AAAAMM.
SELECT PERIOD_ADD(202609, 3); -- 202612PERIOD_DIFF#
PERIOD_DIFF(periode1, periode2)Différence en mois entre deux périodes AAMM/AAAAMM.
SELECT PERIOD_DIFF(202612, 202609); -- 3GET_FORMAT#
GET_FORMAT({DATE | TIME | DATETIME | TIMESTAMP}, {'EUR' | 'USA' | 'JIS' | 'ISO' | 'INTERNAL'})Rend la chaîne de format (compatible DATE_FORMAT) correspondant à une convention régionale nommée, par exemple pour l'utiliser ensuite avec STR_TO_DATE ou DATE_FORMAT. NULL si la combinaison n'est pas définie.
SELECT GET_FORMAT(DATE, 'EUR'); -- '%d.%m.%Y'
SELECT STR_TO_DATE('13.09.2026', GET_FORMAT(DATE, 'EUR')); -- '2026-09-13'
SELECT GET_FORMAT(DATETIME, 'ISO'), GET_FORMAT(TIME, 'USA'); -- '%Y-%m-%d %H:%i:%s', '%h:%i:%s %p'Fuseau horaire de la session#
SET [GLOBAL | SESSION] time_zone = 'SYSTEM' | '+02:00' | 'Europe/Paris' | DEFAULT;
SELECT @@time_zone, @@global.time_zone, @@system_time_zone;time_zone vaut SYSTEM au départ (fuseau de la machine, avec ses passages à l'heure d'été). Les autres valeurs sont un décalage fixe de -13:59 à +14:00 ('+02:00') ou un nom de la base IANA ('Europe/Paris', 'UTC', casse ignorée), fournie avec MIRAJ : aucun fichier système à installer, sous Windows, macOS et Linux. Un fuseau inconnu ou un décalage hors plage rend l'erreur 1298. SET time_zone ne change que la session ; SET GLOBAL time_zone fixe la valeur que reçoivent les sessions ouvertes ensuite (elle n'est pas conservée après un redémarrage du serveur) et DEFAULT reprend la valeur globale.
Le fuseau de la session détermine :
NOW()et ses synonymes,SYSDATE(),CURDATE(),CURTIME(),UNIX_TIMESTAMP()etFROM_UNIXTIME();UTC_TIMESTAMP(),UTC_DATE()etUTC_TIME()restent en UTC ;- les colonnes
TIMESTAMP: la valeur désigne un instant, rangé en UTC (fichiers, index, journaux, réplication, sauvegardes), que chaque session lit et écrit dans son propre fuseau (DEFAULT CURRENT_TIMESTAMPetON UPDATE CURRENT_TIMESTAMPcomprises). Changer le fuseau de la machine ne déplace pas les valeurs rangées (une session enSYSTEMles montre dans le nouveau fuseau), et deux instants de l'heure répétée au passage à l'heure d'hiver restent distincts une fois rangés (clés, index uniques, ordre d'un index), même si une session de ce fuseau les lit à la même heure civile. Les colonnes générées et les valeurs des événements de changement voient une colonneTIMESTAMPà l'heure du fuseau de la machine. Les colonnesDATETIME,DATE,TIMEetYEARgardent l'heure écrite, sans conversion.
SET time_zone = '+00:00';
INSERT INTO t (ts, dt) VALUES ('2026-06-01 12:00:00', '2026-06-01 12:00:00');
SET time_zone = '+05:00';
SELECT ts, dt FROM t; -- '2026-06-01 17:00:00' | '2026-06-01 12:00:00'CAST(expr AS YEAR) convertit un nombre ou une date en année (CAST(69 AS YEAR) : 2069, CAST(70 AS YEAR) : 1970), NULL hors de 1901 à 2155 (0 reste 0) ; un entier de forme AAAAMMJJ[hhmmss] se convertit en DATE ou DATETIME par CAST, et un texte de forme libre ('200101', '2020.01.01', '20200101100000') aussi (voir le chapitre 6). Un DATE ou un DATETIME utilisé dans un calcul prend sa forme numérique (AAAAMMJJhhmmss) : CAST('2020-01-01 10:00:00' AS DATETIME) + 0 vaut 20200101100000.
CONVERT_TZ#
CONVERT_TZ(expr, fuseau_origine, fuseau_cible)Convertit expr du fuseau fuseau_origine vers fuseau_cible. Chaque fuseau est soit 'SYSTEM' (heure locale du serveur), soit un décalage fixe ('+01:00', de -13:59 à +14:00), soit un nom de fuseau IANA ('Europe/Paris', 'UTC', ...). NULL si un fuseau est invalide ou si le résultat sort de la plage des années 1 à 9999 (jamais d'erreur 1298, réservée à SET time_zone). CONVERT_TZ ne dépend pas du time_zone de la session.
Retour : DATETIME.
SELECT CONVERT_TZ('2026-09-13 12:00:00', 'UTC', 'Europe/Paris'); -- '2026-09-13 14:00:00'10.4 Fonctions de contrôle et logique#
Récapitulatif :
| Fonction | Signature |
|---|---|
| IF | IF(condition, valeur_si_vrai, valeur_si_faux) |
| IFNULL / NVL | IFNULL(expr1, expr2) |
| COALESCE | COALESCE(expr1, expr2, ...) |
| NULLIF | NULLIF(expr1, expr2) |
| ISNULL | ISNULL(expr) |
| NVL2 | NVL2(expr, si_non_null, si_null) |
| INTERVAL (rang) | INTERVAL(n, n1, n2, ...) |
| DEFAULT | DEFAULT(colonne) |
| NAME_CONST | NAME_CONST(nom, valeur) |
IF#
IF(condition, valeur_si_vrai, valeur_si_faux)Rend valeur_si_vrai si condition est vraie (non nulle et différente de zéro), sinon valeur_si_faux. Une condition NULL compte comme fausse. Le type de retour est le type commun de valeur_si_vrai et valeur_si_faux (voir le tableau de COALESCE ci-dessous) ; la branche non prise n'est pas évaluée pour son type d'erreur mais compte pour le typage du résultat.
SELECT IF(1 > 0, 'oui', 'non'); -- 'oui'
SELECT IF(NULL, 'oui', 'non'); -- 'non'IFNULL / NVL#
IFNULL(expr1, expr2)Rend expr1 s'il n'est pas NULL, sinon expr2. NVL est un alias strict.
SELECT IFNULL(NULL, 'valeur par défaut'); -- 'valeur par défaut'
SELECT IFNULL('x', 'y'); -- 'x'COALESCE#
COALESCE(expr1, expr2, ...)Rend la première expression non NULL de la liste, ou NULL si toutes le sont.
Type de retour : déduit de tous les arguments — tous entiers → BIGINT ; tous numériques avec un flottant → DOUBLE ; tous numériques sans flottant → DECIMAL (à l'échelle la plus large) ; tous temporels avec un DATETIME → DATETIME, sinon le type du premier argument ; tous VECTOR → VECTOR ; sinon texte. Ces mêmes règles s'appliquent à IF, IFNULL, GREATEST, LEAST et à CASE WHEN.
SELECT COALESCE(NULL, NULL, 'trouvé', 'ignoré'); -- 'trouvé'NULLIF#
NULLIF(expr1, expr2)Rend NULL si expr1 = expr2, sinon expr1 (avec son type et son échelle d'origine, y compris DECIMAL).
SELECT NULLIF(5, 5); -- NULL
SELECT NULLIF(5, 6); -- 5ISNULL#
ISNULL(expr)1 si expr est NULL, 0 sinon. Contrairement à la plupart des fonctions, ne rend jamais NULL elle-même.
Retour : BIGINT.
SELECT ISNULL(NULL); -- 1
SELECT ISNULL(0); -- 0NVL2#
NVL2(expr, si_non_null, si_null)Rend si_non_null si expr n'est pas NULL, si_null sinon. Type du résultat comme IF.
SELECT NVL2(NULL, 'a', 'b'), NVL2(0, 'a', 'b'); -- 'b', 'a'INTERVAL (rang)#
INTERVAL(n, n1, n2, ...)Rang de n dans la liste croissante n1 < n2 < ... : 0 si n < n1, 1 si n1 <= n < n2, et ainsi de suite ; -1 si n est NULL (les éléments NULL de la liste sont ignorés). Deux arguments au moins (sinon erreur de syntaxe 1064). Ne pas confondre avec l'INTERVAL n unité des calculs de dates, qui reste inchangé.
SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200); -- 3DEFAULT#
DEFAULT(colonne)Valeur par défaut déclarée de la colonne (NULL si elle n'en a pas et accepte NULL). Une colonne NOT NULL sans défaut rend l'erreur 1364, une colonne inconnue 1054, une expression qui n'est pas une colonne de table 1210. S'emploie dans une liste de sélection, un WHERE ou un UPDATE (SET a = DEFAULT(a) + 1). VALUES(colonne) hors d'un ON DUPLICATE KEY UPDATE rend NULL.
CREATE TABLE td (id INT PRIMARY KEY, n INT DEFAULT 10, s VARCHAR(5) DEFAULT 'abc');
INSERT INTO td (id) VALUES (1);
SELECT DEFAULT(n), DEFAULT(s) FROM td; -- 10, 'abc'NAME_CONST#
NAME_CONST(nom, valeur)Rend valeur ; nom n'intervient pas dans le calcul (la forme sert aux instructions rejouées par la réplication).
SELECT NAME_CONST('total', 42); -- 42Les comparaisons a IS [NOT] DISTINCT FROM b (équivalent de NOT (a <=> b), NULL comparé comme une valeur) et x IS [NOT] UNKNOWN (test d'un résultat booléen NULL) complètent ces fonctions (voir 10.19).
10.5 Fonctions d'agrégation#
Les fonctions d'agrégation résument les valeurs d'un groupe de lignes (GROUP BY, ou toute la table sans GROUP BY) en une seule valeur. Contrairement aux fonctions scalaires, elles ignorent silencieusement les NULL de leur argument plutôt que de faire échouer tout le calcul.
Ces fonctions, à l'exception de GROUP_CONCAT, JSON_ARRAYAGG, JSON_OBJECTAGG, BIT_*, ANY_VALUE, STDDEV_SAMP, VAR_POP et VAR_SAMP, peuvent aussi s'utiliser comme fonctions de fenêtrage avec OVER (...) : voir 10.13.
Les exemples de cette section utilisent les tables suivantes :
CREATE TABLE clients (id INT PRIMARY KEY, nom VARCHAR(20), ville VARCHAR(20));
INSERT INTO clients VALUES (1,'Ali','Lyon'), (2,'Bob','Paris'), (3,'Chloé','Lyon');
CREATE TABLE commandes (id INT PRIMARY KEY, client_id INT, article_id INT, montant DECIMAL(8,2));
INSERT INTO commandes VALUES (1,1,10,25.00), (2,1,11,40.50), (3,2,10,12.00), (4,3,12,NULL), (5,1,10,30.00);
CREATE TABLE mesures (x INT, b INT);
INSERT INTO mesures VALUES (2,12), (4,10), (4,6), (6,NULL);
CREATE TABLE ventes (region VARCHAR(10), qte INT);
INSERT INTO ventes VALUES ('Nord',10), ('Nord',5), ('Sud',7);
CREATE TABLE parametres (code VARCHAR(10), valeur VARCHAR(10));
INSERT INTO parametres VALUES ('SEUIL','20'), ('JOUR',NULL);Récapitulatif :
| Fonction | Signature |
|---|---|
| COUNT | COUNT(*) <br> COUNT([DISTINCT] expr) |
| SUM | SUM([DISTINCT] expr) |
| AVG | AVG([DISTINCT] expr) |
| MIN / MAX | MIN(expr) <br> MAX(expr) |
| GROUP_CONCAT | GROUP_CONCAT([DISTINCT] expr [, expr2, ...] <br> [ORDER BY cle1 [ASC|DESC], ...] <br> [SEPARATOR chaine] <br> [LIMIT n [OFFSET m] | LIMIT m, n]) |
| STD / STDDEV / STDDEV_POP | STD(expr) <br> STDDEV(expr) <br> STDDEV_POP(expr) |
| STDDEV_SAMP | STDDEV_SAMP(expr) |
| VARIANCE / VAR_POP | VARIANCE(expr) <br> VAR_POP(expr) |
| VAR_SAMP | VAR_SAMP(expr) |
| BIT_AND, BIT_OR, BIT_XOR | BIT_AND(expr) <br> BIT_OR(expr) <br> BIT_XOR(expr) |
| ANY_VALUE | ANY_VALUE(expr) |
| GROUPING | GROUPING(expr [, expr2, ...]) |
| JSON_ARRAYAGG | JSON_ARRAYAGG([DISTINCT] expr <br> [ORDER BY cle1 [ASC|DESC], ...] <br> [LIMIT n [OFFSET m] | LIMIT m, n]) |
| JSON_OBJECTAGG | JSON_OBJECTAGG(cle, valeur) |
| ST_COLLECT | ST_COLLECT([DISTINCT] geometrie) (voir 10.17) |
COUNT#
COUNT(*)
COUNT([DISTINCT] expr)
COUNT(DISTINCT expr, expr2 [, ...])COUNT(*) compte toutes les lignes du groupe. COUNT(expr) compte les lignes où expr n'est pas NULL. COUNT(DISTINCT expr) compte les valeurs distinctes non NULL de expr. COUNT(DISTINCT expr, expr2, ...) compte les combinaisons distinctes de valeurs dont aucune n'est NULL ; chaque texte est comparé selon son interclassement ('a' et 'A' ne font qu'une valeur en utf8mb4_general_ci). Plusieurs expressions ne s'écrivent qu'avec DISTINCT (COUNT(a, b) et COUNT() : erreur de syntaxe 1064), et pas dans une fonction de fenêtrage.
Retour : BIGINT.
SELECT COUNT(*), COUNT(montant) FROM commandes; -- 5, 4
SELECT COUNT(DISTINCT client_id) FROM commandes; -- 3
SELECT COUNT(DISTINCT client_id, article_id) FROM commandes; -- 4SUM#
SUM([DISTINCT] expr)Somme des valeurs non NULL de expr. NULL si le groupe ne contient aucune valeur non NULL. Sur une colonne VECTOR(n), effectue une somme élément par élément (résultat VECTOR(n)).
Retour : BIGINT si expr est entier, DECIMAL (même échelle) si expr est DECIMAL, DOUBLE sinon.
SELECT SUM(montant), SUM(DISTINCT client_id), SUM(id) FROM commandes; -- 107.50, 6, 15AVG#
AVG([DISTINCT] expr)Moyenne des valeurs non NULL de expr. Sur VECTOR(n), moyenne élément par élément.
Retour : DECIMAL avec 4 décimales de plus que expr si expr est entier ou DECIMAL, DOUBLE sinon.
SELECT AVG(montant), AVG(id), AVG(montant * 1e0) FROM commandes; -- 26.875000, 3.0000, 26.875MIN / MAX#
MIN(expr)
MAX(expr)Plus petite / plus grande valeur non NULL de expr selon l'ordre naturel du type (l'interclassement pour un texte). NULL si le groupe ne contient aucune valeur non NULL.
Retour : le type de expr.
SELECT MIN(montant), MAX(montant) FROM commandes; -- 12.00, 40.50
SELECT MIN(nom), MAX(nom) FROM clients; -- 'Ali', 'Chloé'GROUP_CONCAT#
GROUP_CONCAT([DISTINCT] expr [, expr2, ...]
[ORDER BY cle1 [ASC|DESC], ...]
[SEPARATOR chaine]
[LIMIT n | LIMIT m, n | LIMIT n OFFSET m])Concatène les valeurs non NULL de expr du groupe (converties en texte) en une seule chaîne. Avec plusieurs expressions (expr, expr2, ...), chacune est concaténée directement (sans séparateur entre elles) pour chaque ligne, et la ligne entière est ignorée si l'une de ces expressions vaut NULL. DISTINCT élimine les doublons avant concaténation. ORDER BY (avec un numéro de position ou une expression) fixe l'ordre des valeurs dans le résultat — la clé de tri peut être une expression qui n'est pas elle-même concaténée. SEPARATOR fixe le séparateur entre valeurs (',' par défaut) ; SEPARATOR '' ne met aucun séparateur. LIMIT ne garde que n valeurs après en avoir passé m (aucune par défaut), une fois les doublons éliminés et les valeurs triées (dans l'ordre de lecture sans ORDER BY) ; n et m sont des entiers sans signe, des paramètres ? ou des variables d'une routine. Une limite qui ne garde aucune valeur rend un texte vide, et non NULL, pour un groupe qui en a. Les clauses s'écrivent dans cet ordre : ORDER BY, SEPARATOR, LIMIT.
La longueur du résultat est bornée par la variable group_concat_max_len (1 048 576 octets par défaut, de 4 à 4 294 967 295 ; option de démarrage --group-concat-max-len) : au-delà, le texte est tronqué à cette longueur en octets, sans jamais couper un caractère UTF-8, et l'instruction reçoit l'avertissement 1260 (N line(s) were cut by GROUP_CONCAT(), N étant le nombre de groupes tronqués), visible par SHOW WARNINGS. Le texte au-delà de la limite n'est jamais gardé en mémoire, y compris dans une lecture parallèle. SET [SESSION] group_concat_max_len = n change la limite de la session, SET GLOBAL celle des sessions ouvertes ensuite, SET STATEMENT group_concat_max_len = n FOR … celle d'une seule instruction.
Retour : texte.
SELECT GROUP_CONCAT(nom ORDER BY nom SEPARATOR ' ; ') FROM clients;
-- 'Ali ; Bob ; Chloé'
SELECT GROUP_CONCAT(DISTINCT ville) FROM clients;
-- 'Lyon,Paris'
SELECT GROUP_CONCAT(nom ORDER BY nom LIMIT 2 OFFSET 1) FROM clients;
-- 'Bob,Chloé'STD / STDDEV / STDDEV_POP#
STD(expr)
STDDEV(expr)
STDDEV_POP(expr)Écart-type de population des valeurs non NULL de expr (diviseur = nombre de valeurs). Les trois noms sont strictement équivalents. NULL si le groupe est vide.
Retour : DOUBLE.
SELECT STD(x), STDDEV(x), STDDEV_POP(x) FROM mesures; -- 1.4142135623730951, 1.4142135623730951, 1.4142135623730951STDDEV_SAMP#
STDDEV_SAMP(expr)Écart-type corrigé (d'échantillon), diviseur = nombre de valeurs moins un. NULL si le groupe compte moins de deux valeurs.
SELECT STDDEV_SAMP(x) FROM mesures; -- 1.632993161855452VARIANCE / VAR_POP#
VARIANCE(expr)
VAR_POP(expr)Variance de population (carré de STD). Les deux noms sont équivalents.
SELECT VARIANCE(x), VAR_POP(x) FROM mesures; -- 2.0, 2.0VAR_SAMP#
VAR_SAMP(expr)Variance corrigée (carré de STDDEV_SAMP). NULL si le groupe compte moins de deux valeurs.
SELECT VAR_SAMP(x) FROM mesures; -- 2.6666666666666665BIT_AND, BIT_OR, BIT_XOR#
BIT_AND(expr)
BIT_OR(expr)
BIT_XOR(expr)ET, OU et OU exclusif bit à bit de toutes les valeurs entières non NULL de expr (BIT_AND d'un groupe vide vaut tous les bits à 1, BIT_OR et BIT_XOR d'un groupe vide valent 0).
Retour : entier non signé sur 64 bits.
SELECT BIT_AND(b), BIT_OR(b), BIT_XOR(b) FROM mesures; -- 0, 14, 0 (12, 10 et 6)
SELECT BIT_AND(b), BIT_OR(b) FROM mesures WHERE x > 100; -- 18446744073709551615, 0ANY_VALUE#
ANY_VALUE(expr)Une valeur de expr prise dans le groupe (NULL pour un groupe vide), sans garantie sur laquelle. Sert à citer une colonne non agrégée et hors GROUP BY quand sql_mode contient ONLY_FULL_GROUP_BY, qui la refuserait nue (§10.5).
SELECT ville, ANY_VALUE(nom), COUNT(*) FROM clients GROUP BY ville ORDER BY ville;
-- 'Lyon', 'Ali', 2
-- 'Paris', 'Bob', 1GROUPING#
GROUPING(expr [, expr2, ...])Pour un GROUP BY ... WITH ROLLUP, ROLLUP(...), CUBE(...) ou GROUPING SETS (...) (chapitre 9, §9.17) : 1 si la ligne est une ligne de sous-total qui résume expr (la colonne y vaut NULL), 0 si NULL est une vraie valeur ou si la colonne est regroupée. Avec plusieurs arguments, un masque de bits dont le premier argument est le bit de poids fort (GROUPING(a, b) vaut 3 sur le total général). Chaque argument doit être une expression du GROUP BY (erreur 3580) ; GROUPING() sans argument rend 1582, et sa présence dans un WHERE ou sans regroupement 1111. Sans ROLLUP, vaut toujours 0.
Retour : BIGINT.
SELECT IF(GROUPING(region), 'total', IFNULL(region, '?')) AS region, SUM(qte)
FROM ventes GROUP BY region WITH ROLLUP;
-- 'Nord', 15
-- 'Sud', 7
-- 'total', 22JSON_ARRAYAGG#
JSON_ARRAYAGG([DISTINCT] expr
[ORDER BY cle1 [ASC|DESC], ...]
[LIMIT n | LIMIT m, n | LIMIT n OFFSET m])Construit un tableau JSON ([...]) à partir des valeurs de expr du groupe (dans l'ordre de lecture, ou celui de ORDER BY), chaque valeur étant convertie en document JSON scalaire (nombre tel quel, texte entre guillemets, NULL en null) sauf si expr produit déjà un document JSON. DISTINCT élimine les doublons, jugés sur la valeur de expr sous son interclassement comme dans GROUP_CONCAT ('a', 'A' et 'a ' confondus en utf8mb4_general_ci), pas sur son texte JSON ; LIMIT ne garde que n éléments après en avoir passé m, une fois les doublons éliminés et les éléments triés, comme dans GROUP_CONCAT (un NULL reste un élément, trié avant les autres valeurs ; [] si la limite ne garde rien). Le contenu entre les crochets est borné par group_concat_max_len, comme GROUP_CONCAT (avertissement 1260 au-delà ; le tableau tronqué n'est alors plus un document JSON valide).
Retour : texte JSON.
SELECT JSON_ARRAYAGG(nom) FROM clients; -- '["Ali", "Bob", "Chloé"]'
SELECT JSON_ARRAYAGG(nom ORDER BY nom DESC LIMIT 2) FROM clients; -- '["Chloé", "Bob"]'JSON_OBJECTAGG#
JSON_OBJECTAGG(cle, valeur)Construit un objet JSON ({...}) à partir des paires du groupe : chaque cle devient un nom de membre, chaque valeur est convertie comme pour JSON_ARRAYAGG. Une clé répétée garde sa première place et sa dernière valeur ; une clé NULL lève l'erreur 3158. NULL pour un groupe vide. Le contenu est borné par group_concat_max_len, comme pour JSON_ARRAYAGG.
Retour : texte JSON.
SELECT JSON_OBJECTAGG(code, valeur) FROM parametres; -- '{"SEUIL": "20", "JOUR": null}'10.6 Expressions régulières#
MIRAJ implémente les expressions régulières compatibles PCRE (moteur en temps linéaire, sans référence arrière ni assertions de largeur nulle) ; c'est le même moteur que l'opérateur REGEXP/RLIKE. Par défaut, la recherche est insensible à la casse, sauf sous l'interclassement utf8mb4_bin ('ABC' COLLATE utf8mb4_bin REGEXP 'abc' vaut 0) ; le type c / i l'emporte toujours. Les poids ne s'appliquent pas ('é' REGEXP 'e' est faux). Le paramètre facultatif type (dernier argument de chaque fonction) accepte une combinaison des lettres :
| Lettre | Effet |
|---|---|
c | Sensible à la casse |
i | Insensible à la casse (par défaut) |
m | ^ et $ reconnaissent aussi les débuts et fins de ligne |
n | . reconnaît aussi le retour à la ligne |
u | Accepté, sans effet |
Un motif invalide lève une erreur ; un quantificateur appliqué directement à ^ ou $ est refusé.
Récapitulatif :
| Fonction | Signature |
|---|---|
| REGEXP_LIKE | REGEXP_LIKE(expr, motif [, type]) |
| REGEXP_INSTR | REGEXP_INSTR(expr, motif [, position [, occurrence [, option [, type]]]]) |
| REGEXP_SUBSTR | REGEXP_SUBSTR(expr, motif [, position [, occurrence [, type]]]) |
| REGEXP_REPLACE | REGEXP_REPLACE(expr, motif, remplacement [, position [, occurrence [, type]]]) |
REGEXP_LIKE#
REGEXP_LIKE(expr, motif [, type])1 si motif correspond quelque part dans expr, 0 sinon.
Retour : BIGINT.
SELECT REGEXP_LIKE('MIRAJ-1.0', '^[A-Z]+-[0-9.]+$'); -- 1
SELECT REGEXP_LIKE('ABC', 'abc'), REGEXP_LIKE('ABC', 'abc', 'c'); -- 1, 0REGEXP_INSTR#
REGEXP_INSTR(expr, motif [, position [, occurrence [, option [, type]]]])Position (en caractères, base 1) du début de la occurrence-ième correspondance (1 par défaut) à partir de position (1 par défaut) ; 0 si elle n'existe pas. Si option vaut 1, rend la position après la fin de la correspondance plutôt que son début (0 par défaut).
Retour : BIGINT.
SELECT REGEXP_INSTR('abc123def456', '[0-9]+', 1, 2); -- 10 (début du second groupe de chiffres)
SELECT REGEXP_INSTR('abc123def456', '[0-9]+', 1, 2, 1); -- 13 (position après sa fin)REGEXP_SUBSTR#
REGEXP_SUBSTR(expr, motif [, position [, occurrence [, type]]])Texte de la occurrence-ième correspondance de motif dans expr à partir de position. Rend une chaîne vide (pas NULL) si aucune correspondance n'est trouvée.
SELECT REGEXP_SUBSTR('prix: 42.50 EUR', '[0-9]+\\.[0-9]+'); -- '42.50'
SELECT REGEXP_SUBSTR('abc', '[0-9]+'); -- '' (chaîne vide)REGEXP_REPLACE#
REGEXP_REPLACE(expr, motif, remplacement [, position [, occurrence [, type]]])Remplace par remplacement toutes les correspondances de motif à partir de position (toutes, par défaut), ou seulement la occurrence-ième si elle est précisée (> 0). Dans remplacement, \N (N de 0 à 9) insère le texte du N-ième groupe capturé (\0 = correspondance entière) ; un \N sans groupe correspondant insère une chaîne vide.
SELECT REGEXP_REPLACE('2026-09-13', '([0-9]+)-([0-9]+)-([0-9]+)', '\\3/\\2/\\1');
-- '13/09/2026'
SELECT REGEXP_REPLACE('a1b2c3', '[0-9]', '#', 1, 2); -- 'a1b#c3' (deuxième correspondance seulement)10.7 Fonctions de hachage, chiffrement et encodage#
Récapitulatif :
| Fonction | Signature |
|---|---|
| MD5 | MD5(expr) |
| SHA1 / SHA | SHA1(expr) |
| SHA2 | SHA2(expr, longueur_bits) |
| PASSWORD | PASSWORD(mot_de_passe) |
| HEX | HEX(expr) |
| UNHEX | UNHEX(chaine_hex) |
| TO_BASE64 | TO_BASE64(expr) |
| FROM_BASE64 | FROM_BASE64(chaine) |
| AES_ENCRYPT | AES_ENCRYPT(donnees, cle) |
| AES_DECRYPT | AES_DECRYPT(donnees_chiffrees, cle) |
| COMPRESS | COMPRESS(donnees) |
| UNCOMPRESS | UNCOMPRESS(donnees_compressees) |
| UNCOMPRESSED_LENGTH | UNCOMPRESSED_LENGTH(donnees_compressees) |
| OLD_PASSWORD | OLD_PASSWORD(mot_de_passe) |
| ENCODE / DECODE | ENCODE(chaine, mot_de_passe) <br> DECODE(chiffre, mot_de_passe) |
| DES_ENCRYPT / DES_DECRYPT | DES_ENCRYPT(chaine, cle) <br> DES_DECRYPT(chiffre, cle) |
| ENCRYPT | ENCRYPT(mot_de_passe [, sel]) |
| KDF | KDF(cle, sel [, {info | iterations} [, methode [, largeur_bits]]]) |
MD5#
MD5(expr)Empreinte MD5 (RFC 1321) de expr, en hexadécimal minuscule (32 caractères).
Retour : texte.
SELECT MD5('MIRAJ'); -- '58c6d474b82f107c62de4154e2c75ee4'Attention — pas pour des mots de passe :
MD5,SHA1etPASSWORDsont rapides, sans sel et, pour les deux premiers, cassés face aux collisions. Une table d'empreintesMD5(mot_de_passe)ouSHA1(mot_de_passe)se retrouve par dictionnaire ou force brute en quelques minutes sur une carte graphique. Pour les mots de passe d'une application, hachez-les dans l'application avec une fonction lente et salée (Argon2id, scrypt ou bcrypt) et ne stockez que le résultat. Ces fonctions restent utiles pour une somme de contrôle, une clé de déduplication ou la compatibilité.
SHA1 / SHA#
SHA1(expr)Empreinte SHA-1 (FIPS 180-4), en hexadécimal minuscule (40 caractères). SHA est un alias strict.
SELECT SHA1('MIRAJ'); -- 'ed6f42df071e947ccc017ef765bff993f67c1b9c'SHA2#
SHA2(expr, longueur_bits)Empreinte de la famille SHA-2, en hexadécimal minuscule. longueur_bits doit valoir 224, 256, 384, 512, ou 0 (équivalent à 256) ; toute autre valeur rend NULL.
SELECT SHA2('MIRAJ', 256); -- '2e1b6300e6c695f56eae36449ea80f4e35315b99cc1941f9fbb5852ee338e9e8'PASSWORD#
PASSWORD(mot_de_passe)Empreinte utilisée en interne pour authentication_string d'un compte (voir le chapitre 15. Comptes et privilèges). N'est normalement pas nécessaire dans des requêtes applicatives.
SELECT PASSWORD('secret'); -- '*14E65567ABDB5135D0CFD9A70B3032C179A49EE7'Attention :
PASSWORD()est un double SHA-1 sans sel (*suivi de 40 chiffres hexadécimaux), gardé pour la compatibilité du protocole. Ne vous en servez pas pour les mots de passe de votre application (voir l'encadré de MD5) ; et une empreintePASSWORD()ne se communique pas : elle suffit à se connecter au compte avec un client modifié.
HEX#
HEX(expr)Représentation hexadécimale (majuscules) de expr : pour un nombre, sa valeur entière sur 64 bits ; pour une valeur binaire, ses octets bruts ; pour un texte, ses octets UTF-8.
SELECT HEX(255); -- 'FF'
SELECT HEX('AB'); -- '4142'UNHEX#
UNHEX(chaine_hex)Décode chaine_hex (un chiffre de tête implicite 0 est ajouté si sa longueur est impaire) en octets bruts. NULL si chaine_hex contient un caractère qui n'est pas un chiffre hexadécimal.
Retour : binaire (VARBINARY).
SELECT UNHEX('4142'); -- 'AB'TO_BASE64#
TO_BASE64(expr)Encode expr en base64 (alphabet standard, avec remplissage =), en insérant un retour à la ligne tous les 76 caractères.
Retour : texte.
SELECT TO_BASE64('MIRAJ'), TO_BASE64('é'); -- 'TUlSQUo=', 'w6k='
SELECT LOCATE('\n', TO_BASE64(REPEAT('a', 60))); -- 77 (retour à la ligne après 76 caractères)FROM_BASE64#
FROM_BASE64(chaine)Décode chaine (base64 standard) en octets bruts ; les espaces, tabulations et retours à la ligne sont ignorés ; NULL si le texte n'est pas du base64 valide.
Retour : binaire.
SELECT FROM_BASE64(TO_BASE64('MIRAJ')); -- 'MIRAJ'AES_ENCRYPT#
AES_ENCRYPT(donnees, cle)Chiffre donnees en AES-128-ECB (avec bourrage PKCS7), cle étant repliée par OU exclusif sur 16 octets quelle que soit sa longueur (mode par défaut, correspondant à block_encryption_mode = aes-128-ecb).
Retour : binaire.
SELECT HEX(AES_ENCRYPT('secret', 'ma_cle')); -- '9E858F2C52FB8D1AE228315AB3C3B821'Attention — compatibilité seulement, pas une protection des données :
AES_ENCRYPTetAES_DECRYPTreproduisent un format historique, et ce format est faible :
- mode ECB, sans vecteur d'initialisation : deux blocs de 16 octets identiques donnent le même chiffré, si bien que des valeurs égales (ou des débuts de valeurs égaux) se repèrent sans la clé ;
- clé repliée sur 16 octets par OU exclusif, sans dérivation : une phrase de passe courte ou prévisible s'attaque directement, et deux clés différentes peuvent donner la même clé AES ;
- aucune authentification : un chiffré modifié se déchiffre souvent en données fausses sans erreur (le seul contrôle est le bourrage) ;
- la clé voyage dans le texte de la requête : MIRAJ la masque dans ses journaux et dans
SHOW PROCESSLIST, mais tout ce qui voit la requête avant le serveur (application, traces côté client, réseau sans TLS) la voit en clair.Utilisez-les pour relire des données déjà chiffrées ainsi. Pour protéger de nouvelles données, chiffrez-les dans l'application (AES-256-GCM ou ChaCha20-Poly1305, nonce aléatoire, clé gardée hors de la base) et stockez le résultat en
VARBINARY.
AES_DECRYPT#
AES_DECRYPT(donnees_chiffrees, cle)Inverse de AES_ENCRYPT avec la même dérivation de clé. NULL si le déchiffrement échoue (mauvaise clé, données corrompues).
SELECT AES_DECRYPT(AES_ENCRYPT('secret', 'ma_cle'), 'ma_cle'); -- 'secret'COMPRESS#
COMPRESS(donnees)Compresse donnees (texte ou binaire) : la longueur d'origine sur quatre octets, octet de poids faible en tête (30 bits utiles), suivie du flux zlib. Une chaîne vide reste une chaîne vide. Si le résultat se termine par une espace, un point . lui est ajouté, pour qu'une colonne CHAR ou VARCHAR ne la retire pas ; rangez de préférence le résultat dans une colonne VARBINARY ou BLOB.
Retour : binaire.
SELECT HEX(COMPRESS('a')); -- '01000000789C4B040000620062'
SELECT LENGTH(COMPRESS(REPEAT('a', 1000))); -- 21UNCOMPRESS#
UNCOMPRESS(donnees_compressees)Inverse de COMPRESS. Une chaîne vide reste une chaîne vide. Une donnée illisible rend NULL avec un avertissement :
| Avertissement | Cas |
|---|---|
| 1259 | quatre octets au plus, ou flux zlib corrompu ou tronqué |
| 1258 | le flux rend plus d'octets que la longueur annoncée dans l'en-tête |
| 1256 | la longueur annoncée dépasse max_allowed_packet |
Une longueur annoncée plus grande que le contenu réel est sans effet : le contenu décompressé est rendu tel quel.
Retour : binaire.
SELECT UNCOMPRESS(COMPRESS('bonjour')); -- 'bonjour'
SELECT UNCOMPRESS('abc'); -- NULL, avertissement 1259UNCOMPRESSED_LENGTH#
UNCOMPRESSED_LENGTH(donnees_compressees)Longueur d'origine d'une valeur produite par COMPRESS, lue dans son en-tête sans rien décompresser. 0 pour une chaîne vide ; NULL avec l'avertissement 1259 pour une valeur de quatre octets au plus.
Retour : entier.
SELECT UNCOMPRESSED_LENGTH(COMPRESS(REPEAT('a', 30))); -- 30OLD_PASSWORD#
OLD_PASSWORD(mot_de_passe)Ancienne empreinte de mot de passe sur 64 bits : 16 chiffres hexadécimaux minuscules ; chaîne vide pour une chaîne vide. Gardée pour relire d'anciennes données, comme PASSWORD (voir l'encadré de MD5).
Retour : texte.
SELECT OLD_PASSWORD('secret'); -- '428567f408994404'ENCODE / DECODE#
ENCODE(chaine, mot_de_passe)
DECODE(chiffre, mot_de_passe)Brouillage historique symétrique : ENCODE rend une valeur binaire de même longueur que chaine, DECODE la remet en clair avec le même mot de passe. Un mot de passe vide rend la chaîne telle quelle. Aucune sécurité réelle : réservé à la relecture d'anciennes données.
Retour : binaire.
SELECT HEX(ENCODE('MIRAJ', 'cle')); -- 'AB64DE848C'
SELECT DECODE(ENCODE('MIRAJ', 'cle'), 'cle'); -- 'MIRAJ'DES_ENCRYPT / DES_DECRYPT#
DES_ENCRYPT(chaine, cle)
DES_DECRYPT(chiffre, cle)Chiffrement Triple DES (CBC) avec une clé texte : le résultat commence par l'octet FF (clé texte), suivi du chiffré complété jusqu'à un multiple de 8 octets. Seule la forme avec une clé texte est disponible : sans second argument, ou avec un numéro de clé, DES_ENCRYPT rend NULL avec l'avertissement 1105 (DES key file not loaded). DES_DECRYPT rend telle quelle une valeur qui ne porte pas cet en-tête, et NULL si la clé est mauvaise.
Retour : binaire.
SELECT HEX(DES_ENCRYPT('MIRAJ', 'cle')); -- 'FF3775F69B04E0A7CF'
SELECT DES_DECRYPT(DES_ENCRYPT('MIRAJ', 'cle'), 'cle'); -- 'MIRAJ'
SELECT DES_DECRYPT('texte clair', 'cle'); -- 'texte clair'ENCRYPT#
ENCRYPT(mot_de_passe [, sel])Empreinte crypt d'un mot de passe : DES traditionnelle avec un sel de deux caractères (alphabet ./0-9A-Za-z), ou MD5 ($1$sel$), SHA-256 ($5$sel$) et SHA-512 ($6$sel$). Sans sel, un sel DES aléatoire est tiré. NULL si le sel est trop court, invalide ou d'un format inconnu.
Retour : texte.
SELECT ENCRYPT('secret', 'ab'); -- 'abNANd1rDfiNc'
SELECT ENCRYPT('secret', '$1$sel$'); -- '$1$sel$/HICHqRMepslFM4ftMnyL.'
SELECT ENCRYPT('secret', '$5$sel$'); -- '$5$sel$jk8lUuVUlIs9bmXSnJ3Fsqp/qMlaMJy6D0CSZCxTv2B'
SELECT ENCRYPT('secret', 'a'); -- NULLKDF#
KDF(cle, sel [, {info | iterations} [, methode [, largeur_bits]]])Dérive une clé binaire de largeur_bits / 8 octets (128 bits par défaut) à partir de cle et sel. methode vaut 'hkdf' (défaut, HKDF-SHA256 ; le troisième argument est alors le texte info) ou 'pbkdf2_hmac' (PBKDF2-HMAC-SHA256 ; le troisième argument est le nombre d'itérations, 1000 par défaut, de 1 à 10 000 000). Une méthode inconnue, une largeur nulle, négative, non multiple de 8 ou trop grande, ou un nombre d'itérations hors limites lèvent l'erreur 1210.
Retour : binaire.
SELECT HEX(KDF('motdepasse', 'sel')); -- 'DF033C95264D7D131F666FAF915665CE'
SELECT HEX(KDF('motdepasse', 'sel', 1000, 'pbkdf2_hmac')); -- 'E45D453A16A4523E069E4A4D7DCBC3A4'
SELECT LENGTH(KDF('motdepasse', 'sel', 'contexte', 'hkdf', 256)); -- 3210.8 Fonctions réseau (IP)#
Récapitulatif :
| Fonction | Signature |
|---|---|
| INET_ATON | INET_ATON(adresse_ipv4) |
| INET_NTOA | INET_NTOA(entier) |
| INET6_ATON | INET6_ATON(adresse) |
| INET6_NTOA | INET6_NTOA(binaire) |
| IS_IPV4 | IS_IPV4(chaine) |
| IS_IPV6 | IS_IPV6(chaine) |
| IS_IPV4_COMPAT | IS_IPV4_COMPAT(binaire) |
| IS_IPV4_MAPPED | IS_IPV4_MAPPED(binaire) |
INET_ATON#
INET_ATON(adresse_ipv4)Convertit une adresse IPv4 en notation décimale pointée stricte (quatre parties, sans forme abrégée) en son entier 32 bits. NULL si adresse_ipv4 n'est pas une IPv4 valide dans cette notation.
Retour : BIGINT.
SELECT INET_ATON('192.168.1.1'); -- 3232235777INET_NTOA#
INET_NTOA(entier)Inverse de INET_ATON. NULL si entier n'est pas dans [0, 4294967295].
SELECT INET_NTOA(3232235777); -- '192.168.1.1'INET6_ATON#
INET6_ATON(adresse)Convertit une adresse IPv4 ou IPv6 (notation texte) en sa forme binaire (4 octets pour IPv4, 16 pour IPv6). NULL si adresse n'est ni l'une ni l'autre.
Retour : binaire.
SELECT HEX(INET6_ATON('2001:db8::1')); -- '20010DB8000000000000000000000001'
SELECT HEX(INET6_ATON('10.0.0.1')); -- '0A000001'INET6_NTOA#
INET6_NTOA(binaire)Inverse de INET6_ATON : forme texte (abrégée) d'une adresse binaire de 4 ou 16 octets. NULL pour toute autre longueur.
SELECT INET6_NTOA(INET6_ATON('2001:0db8:0000::0001')); -- '2001:db8::1'
SELECT INET6_NTOA(UNHEX('0A000001')); -- '10.0.0.1'IS_IPV4#
IS_IPV4(chaine)1 si chaine est une adresse IPv4 valide, 0 sinon (jamais NULL pour une entrée non NULL).
Retour : BIGINT.
SELECT IS_IPV4('10.0.0.1'), IS_IPV4('10.0.0.256'); -- 1, 0IS_IPV6#
IS_IPV6(chaine)1 si chaine est une adresse IPv6 valide, 0 sinon.
SELECT IS_IPV6('::1'), IS_IPV6('10.0.0.1'); -- 1, 0IS_IPV4_COMPAT#
IS_IPV4_COMPAT(binaire)1 si binaire (16 octets, comme produit par INET6_ATON) est une adresse IPv4 compatible obsolète (::a.b.c.d : douze premiers octets à zéro), 0 sinon.
SELECT IS_IPV4_COMPAT(INET6_ATON('::10.0.0.1')); -- 1IS_IPV4_MAPPED#
IS_IPV4_MAPPED(binaire)1 si binaire est une adresse IPv4 mappée (::ffff:a.b.c.d), 0 sinon.
SELECT IS_IPV4_MAPPED(INET6_ATON('::ffff:10.0.0.1')), IS_IPV4_MAPPED(INET6_ATON('::10.0.0.1')); -- 1, 010.9 Fonctions système, session et verrous#
Récapitulatif :
| Fonction | Signature |
|---|---|
| DATABASE / SCHEMA | DATABASE() |
| VERSION | VERSION() |
| CHARSET | CHARSET(expr) |
| COLLATION | COLLATION(expr) |
| COERCIBILITY | COERCIBILITY(expr) |
| BENCHMARK | BENCHMARK(n, expr) |
| LAST_INSERT_ID | LAST_INSERT_ID() |
| ROW_COUNT | ROW_COUNT() |
| FOUND_ROWS | FOUND_ROWS() |
| CONNECTION_ID | CONNECTION_ID() |
| USER / SESSION_USER / SYSTEM_USER | USER() |
| CURRENT_USER | CURRENT_USER() |
| CURRENT_ROLE | CURRENT_ROLE() |
| SLEEP | SLEEP(secondes) |
| UUID / UUID_V4 | UUID() <br> UUID_V4() |
| UUID_V7 | UUID_V7() |
| SYS_GUID | SYS_GUID() |
| UUID_SHORT | UUID_SHORT() |
| GET_LOCK | GET_LOCK(nom, delai) |
| RELEASE_LOCK | RELEASE_LOCK(nom) |
| IS_FREE_LOCK | IS_FREE_LOCK(nom) |
| IS_USED_LOCK | IS_USED_LOCK(nom) |
| RELEASE_ALL_LOCKS | RELEASE_ALL_LOCKS() |
| MIRAJ_NOTIFY | MIRAJ_NOTIFY(canal [, charge]) |
| MIRAJ_CHANGE_SEQ | MIRAJ_CHANGE_SEQ() |
| BINLOG_GTID_POS | BINLOG_GTID_POS(fichier, position) |
| MASTER_GTID_WAIT | MASTER_GTID_WAIT(position_gtid [, delai]) |
| MASTER_POS_WAIT | MASTER_POS_WAIT(fichier, position [, delai [, canal]]) |
| DECODE_HISTOGRAM | DECODE_HISTOGRAM(type, histogramme) |
DATABASE / SCHEMA#
DATABASE()Nom de la base courante de la session, NULL si aucune base n'est sélectionnée. SCHEMA est un alias strict. Fonction constante (une seule évaluation par instruction).
USE test;
SELECT DATABASE(), SCHEMA(); -- 'test', 'test'VERSION#
VERSION()Numéro de version du serveur MIRAJ, au format compatible avec les connecteurs existants : 9.0.40-miraj-1.0.0, identique à @@version et à SHOW VARIABLES LIKE 'version'. Le numéro de tête, 9.0.40, est celui que le serveur annonce seul dans la poignée de main du protocole : les connecteurs et les applications le comparent aux numéros de version qu'ils attendent pour activer leurs fonctions (WordPress, par exemple, exige au moins 5.5.5 et n'installe pas sinon). Suivent le nom et la version du produit (voir le chapitre 1. Introduction pour les variables qui distinguent les éditions).
Retour : texte.
SELECT VERSION(); -- '8.0.40-miraj-1.0.0'CHARSET#
CHARSET(expr)Jeu de caractères de expr : utf8mb4 pour un texte (littéral, colonne), binary pour un nombre, une date, NULL ou une valeur binaire ; latin1 ou utf8mb3 pour CONVERT(... USING jeu). Une colonne inconnue rend 1054. CHARSET, COLLATION et COERCIBILITY prennent exactement un argument : CHARSET() ou CHARSET(a, b) est une erreur de syntaxe (1064), et non 1582.
SELECT CHARSET('a'), CHARSET(1), CHARSET(CONVERT('a' USING latin1)); -- 'utf8mb4', 'binary', 'latin1'COLLATION#
COLLATION(expr)Interclassement de expr : celui de la colonne ou de COLLATE (utf8mb4_general_ci par défaut d'un littéral, utf8mb4_unicode_ci, utf8mb4_bin, voir le chapitre 13), celui de l'opérande retenu pour CONCAT, UPPER, etc. ; binary pour un nombre, une date ou NULL.
SELECT COLLATION('a'), COLLATION('a' COLLATE utf8mb4_bin), COLLATION(1); -- 'utf8mb4_general_ci', 'utf8mb4_bin', 'binary'COERCIBILITY#
COERCIBILITY(expr)Priorité d'interclassement de expr, qui sert à arbitrer entre deux textes d'interclassements différents : 0 pour un COLLATE explicite, 2 pour une colonne, 3 pour une fonction système (USER()), 4 pour un CAST(... AS CHAR), 6 pour un littéral texte, 7 pour un nombre, 8 pour NULL. Détail au chapitre 13.
SELECT COERCIBILITY('a' COLLATE utf8mb4_bin), COERCIBILITY(USER()), COERCIBILITY(CAST(1 AS CHAR)), COERCIBILITY('a');
-- 0, 3, 4, 6
SELECT COERCIBILITY(1), COERCIBILITY(NULL); -- 7, 8BENCHMARK#
BENCHMARK(n, expr)Fonction de mesure : rend toujours 0 (MIRAJ n'évalue pas expr n fois). BENCHMARK(NULL, x) rend NULL, BENCHMARK(-1, x) aussi, avec l'avertissement 1411.
SELECT BENCHMARK(1000, MD5('a')), BENCHMARK(NULL, 1); -- 0, NULLLAST_INSERT_ID#
LAST_INSERT_ID()Dernière valeur de colonne auto-incrémentée générée par une instruction INSERT de la session.
LAST_INSERT_ID(expr) fixe en plus cette valeur à expr (et la rend) : LAST_INSERT_ID(55) puis LAST_INSERT_ID() valent 55, comme @@last_insert_id. Avec NULL, la valeur devient 0. Les appels d'une même instruction s'évaluent dans l'ordre des lignes. Après un INSERT de plusieurs lignes, c'est la valeur générée pour la première ligne.
Retour : BIGINT.
CREATE TABLE ai (id INT AUTO_INCREMENT PRIMARY KEY, x INT);
INSERT INTO ai (x) VALUES (1), (2), (3);
SELECT LAST_INSERT_ID(); -- 1
SELECT LAST_INSERT_ID(55), LAST_INSERT_ID(); -- 55, 55ROW_COUNT#
ROW_COUNT()Nombre de lignes affectées par la dernière instruction INSERT, UPDATE ou DELETE de la session.
UPDATE ai SET x = x + 1 WHERE id > 1;
SELECT ROW_COUNT(); -- 2FOUND_ROWS#
FOUND_ROWS()Nombre de lignes du dernier résultat lu (usage historique, propre à la connexion). Après un SELECT SQL_CALC_FOUND_ROWS ... LIMIT n, nombre de lignes que le SELECT aurait rendues sans son LIMIT : SELECT SQL_CALC_FOUND_ROWS id FROM t LIMIT 2; SELECT FOUND_ROWS(); rend le total de t.
SELECT SQL_CALC_FOUND_ROWS id FROM ai LIMIT 2; -- 2 lignes
SELECT FOUND_ROWS(); -- 3CONNECTION_ID#
CONNECTION_ID()Identifiant de connexion de la session courante, tel qu'affiché par SHOW PROCESSLIST.
SELECT CONNECTION_ID(); -- par exemple 12USER / SESSION_USER / SYSTEM_USER#
USER()Identité du client telle que fournie à la connexion, au format 'utilisateur@hôte' (hôte du client, pas celui du compte). SESSION_USER et SYSTEM_USER sont des alias stricts. Dans une routine SQL SECURITY DEFINER, USER() reste le compte de la connexion : seul CURRENT_USER() y rend le définisseur.
SELECT USER(), SESSION_USER(), SYSTEM_USER(); -- 'root@localhost', 'root@localhost', 'root@localhost'CURRENT_USER#
CURRENT_USER()Compte réellement utilisé pour les vérifications de privilèges, au format 'utilisateur@hôte' (l'hôte défini pour le compte, qui peut différer de celui de USER() si le compte a une entrée générique comme '%'). S'écrit aussi sans parenthèses (CURRENT_USER).
SELECT CURRENT_USER(), CURRENT_USER; -- 'root@localhost', 'root@localhost'CURRENT_ROLE#
CURRENT_ROLE()Rôles actifs de la session, ou la chaîne 'NONE' si aucun rôle n'est actif (voir le chapitre 15. Comptes et privilèges).
SELECT CURRENT_ROLE(); -- 'NONE'SLEEP#
SLEEP(secondes)Suspend l'exécution pendant secondes (fractions acceptées), puis rend 0. Un argument NULL ou négatif ne fait pas attendre (rend 0 immédiatement). Un appel n'attend jamais plus d'une heure : une valeur plus grande est ramenée à 3 600 secondes, sans avertissement (un SLEEP démesuré, par erreur ou par malveillance, ne tient plus une session et un fil du serveur pendant des jours). L'attente est interruptible : KILL QUERY sur la session l'abrège et SLEEP rend 1 ; KILL CONNECTION ou le dépassement de max_statement_time lèvent une erreur plutôt que de rendre une valeur.
Retour : BIGINT.
SELECT SLEEP(0.5); -- attend une demi-seconde, rend 0UUID / UUID_V4#
UUID()
UUID_V4()Identifiant UUID version 4 aléatoire, en minuscules (xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx). UUID_V4 est un alias strict.
Ses 122 bits aléatoires viennent d'un générateur cryptographique (ChaCha, amorcé et réamorcé par le système), distinct de celui de RAND() : un UUID ne se déduit ni des précédents ni des valeurs de RAND(). Il peut donc servir d'identifiant difficile à deviner (lien de partage, jeton). Pour un secret brut (sel, clé, jeton binaire), préférez RANDOM_BYTES.
Retour : texte.
SELECT UUID(); -- par exemple '7a6ba694-a7f0-45b8-af54-3fbdfb8ed614'
SELECT UUID_V4(); -- par exemple '65fe50fe-cd82-4979-96c2-f73a0e6256f8'UUID_V7#
UUID_V7()Identifiant UUID version 7, ordonné dans le temps : les 48 premiers bits portent l'instant en millisecondes, la suite est aléatoire. Deux valeurs successives se trient dans l'ordre de leur création, ce qui en fait une bonne clé primaire textuelle (insertions en fin d'index). Nouvelle valeur à chaque appel et à chaque ligne.
Retour : texte.
SELECT UUID_V7(); -- par exemple '01a151fb-ce7c-7000-a185-3b114b9e8c8c'SYS_GUID#
SYS_GUID()Le même identifiant que UUID, écrit sans tirets : 32 chiffres hexadécimaux en minuscules. Comme UUID(), chaque appel et chaque ligne donnent une nouvelle valeur ; la fonction est refusée dans une contrainte CHECK et une colonne générée, et admise en valeur par défaut (DEFAULT SYS_GUID()).
Retour : texte.
SELECT SYS_GUID(); -- par exemple '499fae041ce14b428ded02de5582f5c8'RANDOM_BYTES#
RANDOM_BYTES(n)n octets aléatoires tirés directement du générateur du système d'exploitation (qualité cryptographique), pour un sel, une clé, un vecteur d'initialisation ou un jeton. n va de 1 à 1024 ; hors de cet intervalle, erreur 1690 (length value is out of range in 'random_bytes'). NULL si n est NULL. Jamais évaluée comme une constante : chaque appel, chaque ligne, donne une nouvelle valeur.
Retour : binaire (VARBINARY).
SELECT HEX(RANDOM_BYTES(16)); -- par exemple '194E96E9343C758A83AC7012CC2E1502'
SELECT LENGTH(RANDOM_BYTES(32)); -- 32UUID_SHORT#
UUID_SHORT()Identifiant entier croissant, unique dans le temps : chaque appel rend la valeur précédente plus un.
Retour : BIGINT.
SELECT UUID_SHORT(), UUID_SHORT(); -- par exemple 102128687452782593, 102128687452782594GET_LOCK#
GET_LOCK(nom, delai)Tente de prendre un verrou nommé nom (64 caractères au plus) pour la session. Rend 1 si le verrou est pris (les prises répétées par la même session se cumulent), 0 si delai secondes (fraction permise ; NULL = 0) s'écoulent sans y parvenir, NULL si l'attente est interrompue par KILL QUERY ou hors de toute session. Un délai négatif (« attente illimitée ») ou supérieur à un an est ramené à un an, comme les autres délais du serveur. Lève une erreur si KILL CONNECTION survient, si max_statement_time est dépassé, ou si l'attente fermerait un cycle entre verrous nommés (interblocage détecté).
Une session tient au plus 1 024 verrous nommés distincts à la fois (les reprises d'un verrou qu'elle tient déjà ne comptent pas) : au-delà, GET_LOCK lève l'erreur 1210 (Arguments incorrects pour GET_LOCK (1024 verrous nommés distincts au plus par session)) sans rien prendre. RELEASE_LOCK ou RELEASE_ALL_LOCKS libèrent des places.
Retour : BIGINT.
SELECT GET_LOCK('verrou_import', 10); -- 1
-- ... traitement protégé ...
SELECT RELEASE_LOCK('verrou_import'); -- 1RELEASE_LOCK#
RELEASE_LOCK(nom)Rend une prise du verrou nom détenue par la session. 1 si une prise a été rendue, 0 si le verrou est détenu par une autre session, NULL s'il n'est pas détenu du tout.
SELECT GET_LOCK('verrou', 1), RELEASE_LOCK('verrou'), RELEASE_LOCK('verrou'); -- 1, 1, NULLIS_FREE_LOCK#
IS_FREE_LOCK(nom)1 si personne ne détient le verrou nom, 0 sinon.
SELECT IS_FREE_LOCK('verrou'), GET_LOCK('verrou', 1), IS_FREE_LOCK('verrou'); -- 1, 1, 0IS_USED_LOCK#
IS_USED_LOCK(nom)Identifiant de connexion de la session qui détient le verrou nom, NULL s'il est libre.
SELECT GET_LOCK('verrou', 1), IS_USED_LOCK('verrou') = CONNECTION_ID(), IS_USED_LOCK('autre'); -- 1, 1, NULLRELEASE_ALL_LOCKS#
RELEASE_ALL_LOCKS()Rend toutes les prises de verrous nommés de la session courante ; rend leur nombre.
Retour : BIGINT.
SELECT GET_LOCK('a', 0), GET_LOCK('b', 0), RELEASE_ALL_LOCKS(); -- 1, 1, 2MIRAJ_NOTIFY#
MIRAJ_NOTIFY(canal [, charge])Forme fonction de NOTIFY canal, charge (chapitre 21, §21.4) : la notification est publiée aux abonnés du canal à la validation de la transaction de l'instruction, jamais si elle échoue ou est annulée. Rend 1. Un canal NULL ou vide lève l'erreur 1210, une charge trop longue (--change-events-max-payload) l'erreur 9010 ; éditions Entreprise et Cluster (9001 en édition Express).
Retour : BIGINT.
SELECT MIRAJ_NOTIFY('canal', 'charge'); -- 1MIRAJ_CHANGE_SEQ#
MIRAJ_CHANGE_SEQ()Dernier numéro d'événement de changement publié par le serveur (ou sa base de numérotation, tirée de l'horloge au démarrage, s'il n'en a publié aucun) : point de reprise d'un abonné qui veut tout relire (LISTEN … FROM, chapitre 21, §21.3). Éditions Entreprise et Cluster.
Retour : BIGINT.
SELECT MIRAJ_CHANGE_SEQ(); -- par exemple 1792376684321324BINLOG_GTID_POS#
BINLOG_GTID_POS(fichier, position)État GTID du journal binaire à la position donnée d'un de ses fichiers (voir le chapitre 17). NULL si un argument est NULL, si le fichier est inconnu ou si la position est au-delà de sa fin.
Retour : texte.
SELECT BINLOG_GTID_POS('absent.000001', 4); -- NULL (fichier inconnu)MASTER_GTID_WAIT#
MASTER_GTID_WAIT(position_gtid [, delai])Sur un réplica, attend que la position GTID donnée ('domaine-serveur-numéro', plusieurs séparées par des virgules) ait été appliquée, au plus delai secondes (sans fin si omis). Rend 0 quand la position est atteinte, -1 si le délai s'écoule. Une position mal formée lève l'erreur 1210.
Retour : BIGINT.
SELECT MASTER_GTID_WAIT('0-1-1', 0); -- -1 (rien n'a été appliqué sur ce serveur)MASTER_POS_WAIT#
MASTER_POS_WAIT(fichier, position [, delai [, canal]])Sur un réplica, attend que la source ait été appliquée jusqu'à la position donnée de son journal binaire. Rend le nombre d'événements attendus, -1 si le délai s'écoule, NULL si la réplication ne tourne pas.
Retour : BIGINT.
SELECT MASTER_POS_WAIT('miraj-bin.000002', 4, 0); -- NULL (aucune réplication en cours)DECODE_HISTOGRAM#
DECODE_HISTOGRAM(type, histogramme)Écrit en clair un histogramme binaire de statistiques de colonne : 'SINGLE_PREC_HB' lit un octet par seau (valeur / 255), 'DOUBLE_PREC_HB' deux octets par seau, octet de poids faible en tête (valeur / 65535), chaque seau étant écrit avec trois décimales et séparé du suivant par une virgule ; 'JSON_HB' rend le texte tel quel. Un autre type rend NULL.
Retour : texte.
SELECT DECODE_HISTOGRAM('SINGLE_PREC_HB', UNHEX('3F7FBFFF')); -- '0.247,0.498,0.749,1.000'
SELECT DECODE_HISTOGRAM('DOUBLE_PREC_HB', UNHEX('FF3FFF7F')); -- '0.250,0.500'Variables système @@nom#
En complément des fonctions ci-dessus, une expression peut lire une variable système de session ou globale par @@nom ou @@session.nom / @@local.nom / @@global.nom (par exemple @@version, @@miraj_edition, @@max_allowed_packet). Ces variables sont décrites au chapitre 16. Administration du serveur ; elles se manipulent avec SET et se consultent aussi par SHOW VARIABLES. Une variable utilisateur @nom (propre à la session, NULL tant qu'elle n'a rien reçu) se lit de même et s'affecte dans une expression par @nom := valeur (voir 10.19).
SELECT @@version, @@session.sql_mode, @@GLOBAL.max_connections, @@autocommit;
-- '8.0.40-miraj-1.0.0', 'STRICT_TRANS_TABLES', 151, 110.10 Fonctions JSON#
MIRAJ porte un document JSON comme une simple valeur texte, écrite sous la forme {"a": 1, "b": [1, 2]} (espace après : et après chaque virgule). L'ordre des membres d'un objet est conservé tel qu'écrit, et un nombre garde son écriture d'origine (1.50 reste 1.50).
Échappements des chaînes. Une chaîne d'un document (valeur ou nom de membre) garde le texte écrit entre ses guillemets, échappements compris ("\u00e9", "http:\/\/x.fr", "\x") :
- les fonctions qui rendent du JSON le rendent tel quel :
JSON_EXTRACT(et->),JSON_QUERY,JSON_SET/JSON_INSERT/JSON_REPLACE/JSON_REMOVE/JSON_ARRAY_APPEND/JSON_ARRAY_INSERT(le reste du document n'est pas réécrit : un document produit par PHPjson_encodegarde ses\u00e9et\/),JSON_MERGE_PRESERVE/JSON_MERGE_PATCH,JSON_COMPACT/JSON_LOOSE/JSON_DETAILED/JSON_NORMALIZE/JSON_PRETTY,JSON_KEYS,JSON_OBJECT_TO_ARRAY,JSON_KEY_VALUE,JSON_UNQUOTEd'un objet ou d'un tableau,JSON_SEARCH(chemins rendus) et la colonneJSONdeJSON_TABLE; - les fonctions qui rendent un texte SQL le décodent :
JSON_UNQUOTE(et->>) d'une chaîne,JSON_VALUE, les colonnes deJSON_TABLE;JSON_SEARCHcompare son motif au texte décodé ; une valeur extraite comparée à un texte SQL l'est sans guillemets, décodée (JSON_EXTRACT('["\u0041"]', '$[0]') = 'A'vaut 1) ; - les comparaisons de documents portent sur le texte écrit :
JSON_EQUALS,JSON_CONTAINS,JSON_OVERLAPS,JSON_ARRAY_INTERSECT,JSON_OBJECT_FILTER_KEYSetJSON_SCHEMA_VALID(enum,const,pattern,required,properties...,minLength/maxLengthcomptés en octets de ce texte) distinguent"\u0041"de"A"(JSON_CONTAINS('["\u0041"]', '"A"')vaut 0) ; seulsJSON_CONTAINSetJSON_OVERLAPSretrouvent un membre d'objet par son nom décodé (JSON_CONTAINS('{"\u0041": 1}', '{"A": 1}')vaut 1).MEMBER OF(extension MIRAJ) compare les textes décodés ; - une clé de chemin désigne le membre de même nom décodé (
$.Aet$."\u0041"désignent le membre"\u0041") pourJSON_VALUE,JSON_QUERY,JSON_EXISTS,JSON_SET& co.,JSON_REMOVE,JSON_KEYS,JSON_LENGTH,JSON_CONTAINS,JSON_KEY_VALUEet les colonnes deJSON_TABLE; le membre de même nom écrit pourJSON_EXTRACT(et->),JSON_CONTAINS_PATH, les chemins deJSON_SEARCHet le chemin des lignes (etNESTED PATH) deJSON_TABLE(seul$."\u0041"désigne alors ce membre). Un membre ajouté parJSON_SETprend le nom écrit dans le chemin.
Une chaîne venue du SQL (JSON_OBJECT, JSON_ARRAY, JSON_QUOTE, valeur de JSON_SET) est écrite avec ", \ et les caractères de contrôle échappés, le reste tel quel (/ et é non échappés).
Les fonctions se répartissent en trois familles : construction et validation (JSON_OBJECT, JSON_ARRAY, fusions, JSON_QUOTE, JSON_VALID), lecture par chemin (JSON_EXTRACT et l'opérateur ->, JSON_UNQUOTE et ->>, JSON_VALUE, JSON_CONTAINS, JSON_SEARCH...) et modification (JSON_SET, JSON_INSERT, JSON_REPLACE, JSON_REMOVE, JSON_ARRAY_APPEND, JSON_ARRAY_INSERT). Les agrégats JSON_ARRAYAGG et JSON_OBJECTAGG sont décrits avec les fonctions d'agrégation.
Récapitulatif :
| Fonction | Signature |
|---|---|
| JSON_OBJECT | JSON_OBJECT([cle1, valeur1, cle2, valeur2, ...]) |
| JSON_ARRAY | JSON_ARRAY([valeur1, valeur2, ...]) |
| JSON_MERGE_PRESERVE / JSON_MERGE | JSON_MERGE_PRESERVE(document1, document2, ...) |
| JSON_MERGE_PATCH | JSON_MERGE_PATCH(document1, document2, ...) |
| JSON_QUOTE | JSON_QUOTE(chaine) |
| JSON_VALID | JSON_VALID(chaine) |
Opérateurs -> et ->> | colonne->'chemin' <br> colonne->>'chemin' |
| JSON_EXTRACT | JSON_EXTRACT(document, chemin [, chemin ...]) |
| JSON_UNQUOTE | JSON_UNQUOTE(texte) |
| JSON_VALUE | JSON_VALUE(document, chemin [RETURNING type] [... ON EMPTY] [... ON ERROR]) |
| JSON_SET / JSON_INSERT / JSON_REPLACE | JSON_SET(document, chemin, valeur [, chemin, valeur ...]) |
| JSON_REMOVE | JSON_REMOVE(document, chemin [, chemin ...]) |
| JSON_ARRAY_APPEND / JSON_ARRAY_INSERT | JSON_ARRAY_APPEND(document, chemin, valeur [, ...]) |
| JSON_CONTAINS | JSON_CONTAINS(cible, candidat [, chemin]) |
| JSON_CONTAINS_PATH | JSON_CONTAINS_PATH(document, 'one' | 'all', chemin [, ...]) |
| JSON_KEYS | JSON_KEYS(document [, chemin]) |
| JSON_LENGTH | JSON_LENGTH(document [, chemin]) |
| JSON_DEPTH | JSON_DEPTH(document) |
| JSON_TYPE | JSON_TYPE(document) |
| JSON_SEARCH | JSON_SEARCH(document, 'one' | 'all', motif [, echappement [, chemin ...]]) |
| JSON_OVERLAPS | JSON_OVERLAPS(document1, document2) |
| MEMBER OF | valeur MEMBER OF (document) |
| JSON_PRETTY | JSON_PRETTY(document [, indentation]) |
| JSON_QUERY | JSON_QUERY(document, chemin) |
| JSON_EXISTS | JSON_EXISTS(document, chemin) |
| JSON_EQUALS | JSON_EQUALS(document1, document2) |
| JSON_NORMALIZE | JSON_NORMALIZE(document) |
| JSON_COMPACT / JSON_LOOSE / JSON_DETAILED | JSON_COMPACT(document) <br> JSON_LOOSE(document) <br> JSON_DETAILED(document [, indentation]) |
| JSON_ARRAY_INTERSECT | JSON_ARRAY_INTERSECT(tableau1, tableau2) |
| JSON_OBJECT_FILTER_KEYS | JSON_OBJECT_FILTER_KEYS(objet, tableau_de_cles) |
| JSON_OBJECT_TO_ARRAY | JSON_OBJECT_TO_ARRAY(objet) |
| JSON_KEY_VALUE | JSON_KEY_VALUE(document, chemin) |
| JSON_SCHEMA_VALID / JSON_SCHEMA_VALIDATION_REPORT | JSON_SCHEMA_VALID(schema, document) <br> JSON_SCHEMA_VALIDATION_REPORT(schema, document) |
| JSON_TABLE | FROM JSON_TABLE(document, chemin COLUMNS (...)) [AS] alias |
JSON_OBJECT#
JSON_OBJECT([cle1, valeur1, cle2, valeur2, ...])Construit un objet JSON à partir de paires clé/valeur (nombre pair d'arguments obligatoire). Chaque cle est convertie en texte JSON ; chaque valeur est convertie en scalaire JSON (nombre tel quel, texte entre guillemets échappés, NULL en null) sauf si elle est déjà un document JSON (produit par une autre fonction JSON ou un CAST(... AS JSON)). Une clé NULL lève une erreur.
Retour : texte JSON ; chaîne binaire si une clé ou une valeur est une chaîne binaire (x'…', CAST(… AS BINARY), colonne VARBINARY / BLOB, ou CHAR(n) sans USING écrit en argument) : ses octets sont gardés tels quels (sauf ", \ et les caractères de contrôle, échappés), un texte y est écrit avec un octet par caractère jusqu'à U+00FF et en \uXXXX au-delà (JSON_ARRAY('é', CHAR(1)) rend les octets [", E9, ", "\u0001"]). Même règle pour JSON_ARRAY.
SELECT JSON_OBJECT('nom', 'MIRAJ', 'version', 1.0);
-- '{"nom": "MIRAJ", "version": 1.0}'JSON_ARRAY#
JSON_ARRAY([valeur1, valeur2, ...])Construit un tableau JSON à partir de ses arguments (mêmes règles de conversion que JSON_OBJECT).
SELECT JSON_ARRAY(1, 'deux', NULL); -- '[1, "deux", null]'JSON_MERGE_PRESERVE / JSON_MERGE#
JSON_MERGE_PRESERVE(document1, document2, ...)Fusionne au moins deux documents JSON : deux tableaux sont mis bout à bout ; deux objets sont réunis (les valeurs d'une clé présente dans les deux sont elles-mêmes fusionnées récursivement) ; toute autre combinaison (par ex. un objet et un tableau) traite chaque valeur isolée comme un tableau à un élément puis les met bout à bout. JSON_MERGE est un alias strict.
SELECT JSON_MERGE_PRESERVE('{"a": 1}', '{"a": 2, "b": 3}'); -- '{"a": [1, 2], "b": 3}'
SELECT JSON_MERGE_PRESERVE('[1, 2]', '[true, false]'); -- '[1, 2, true, false]'JSON_MERGE_PATCH#
JSON_MERGE_PATCH(document1, document2, ...)Fusion selon la RFC 7396 : les membres du document suivant remplacent ceux du précédent, un membre valant null retire la clé correspondante ; un document qui n'est pas un objet remplace entièrement le précédent. NULL si un document est NULL (sauf s'il est suivi d'un document qui n'est pas un objet, qui l'emporte quand même).
SELECT JSON_MERGE_PATCH('{"a": 1, "b": 2}', '{"a": null, "c": 3}'); -- '{"b": 2, "c": 3}'JSON_QUOTE#
JSON_QUOTE(chaine)Entoure chaine de guillemets doubles et échappe les caractères spéciaux JSON (caractère de contrôle en \u001F, chiffres majuscules), pour produire une chaîne JSON valide à partir d'un texte SQL brut. Une chaîne binaire (x'e9', CHAR(233)) est lue en latin1, un caractère par octet ("é") ; de même pour la valeur placée par JSON_SET & co.
SELECT JSON_QUOTE('a "b" c'); -- '"a \"b\" c"'JSON_VALID#
JSON_VALID(chaine)1 si chaine est un document JSON syntaxiquement valide, 0 sinon.
Retour : BIGINT.
SELECT JSON_VALID('{"a": 1}'), JSON_VALID('{a: 1}'), JSON_VALID('[1'); -- 1, 0, 0Chemins JSON#
Les fonctions de lecture et de modification désignent une partie d'un document par un chemin, écrit comme une chaîne :
| Élément | Désigne |
|---|---|
$ | le document entier (tout chemin commence par $) |
.cle | le membre cle d'un objet (identifiant : lettres, chiffres, _, $) |
."cle quelconque" | un membre dont le nom contient des espaces ou d'autres caractères |
[n] | la case n d'un tableau (à partir de 0) |
[last], [last-n] | la dernière case, l'avant-dernière ([last-1])... |
[m to n] | les cases m à n (bornes comprises, last permis) |
.* | tous les membres d'un objet |
[*] | toutes les cases d'un tableau |
** | la valeur et toute sa descendance ; suivi d'une autre étape ($**.prix : tous les membres prix, à toute profondeur) |
Un indice appliqué à une valeur qui n'est pas un tableau la traite comme un tableau d'un seul élément : $.a[0] désigne $.a elle-même. Les jokers (.*, [*], **) et les plages ne sont permis que par les fonctions de lecture qui peuvent rendre plusieurs valeurs (JSON_EXTRACT, JSON_CONTAINS_PATH, JSON_SEARCH) ; ailleurs la fonction rend NULL avec l'avertissement 4044, sauf JSON_VALUE et JSON_QUERY, qui rendent NULL sans avertissement, et JSON_EXISTS, qui les accepte. Un chemin mal écrit ou un document invalide ne lève pas d'erreur : la fonction rend NULL avec un avertissement (SHOW WARNINGS) qui cite l'argument et la fonction — 4041 (chemin inachevé) ou 4042 (position du caractère fautif) pour un chemin, 4037 (texte inachevé), 4038 (position) ou 4036 (caractère de contrôle dans une chaîne, position) pour un document. Un échappement inconnu dans une chaîne (\x) vaut le caractère lui-même. Un argument numérique ou temporel passé comme document est lu sous sa forme texte : JSON_EXTRACT(12, '$') rend 12, une date lève l'avertissement 4038.
Sauf mention contraire, un argument NULL (document ou chemin) donne NULL.
SELECT JSON_EXTRACT('{"a": [1]}', '$.a[0]'), JSON_EXTRACT('[1, 2, 3, 4]', '$[last]'), JSON_EXTRACT('[1, 2, 3, 4]', '$[1 to 2]');
-- '1', '4', '[2, 3]'Opérateurs -> et ->>#
colonne->'chemin'
colonne->>'chemin'colonne->'$.a' équivaut à JSON_EXTRACT(colonne, '$.a') (valeur rendue comme document : une chaîne garde ses guillemets) ; colonne->>'$.a' équivaut à JSON_UNQUOTE(JSON_EXTRACT(colonne, '$.a')) (texte sans guillemets). Le chemin doit être une chaîne écrite. Les opérateurs s'utilisent partout où une expression est permise : liste de SELECT, WHERE, ORDER BY, GROUP BY, arguments de fonctions.
CREATE TABLE fiches (id INT PRIMARY KEY, doc JSON);
INSERT INTO fiches VALUES (1, '{"nom": "Ali", "age": 30}'), (2, '{"nom": "Bob", "age": 25}'),
(3, '{"nom": "Chloé", "age": 41}');
SELECT doc->'$.nom', doc->>'$.nom' FROM fiches WHERE id = 1; -- '"Ali"', 'Ali'
SELECT id, doc->>'$.nom' AS nom FROM fiches WHERE doc->'$.age' > 26 ORDER BY doc->>'$.nom';
-- 1, 'Ali'
-- 3, 'Chloé'Une valeur extraite comparée à un texte (doc->'$.nom' = 'Ali', IN ('Ali', …)) est comparée sans ses guillemets, comme une chaîne JSON face à une chaîne SQL ; c'est vrai aussi face à un document (colonne JSON, JSON_QUOTE…), et de deux valeurs extraites comparées l'une à l'autre, seule celle de gauche perd ses guillemets (JSON_EXTRACT('["A"]', '$[0]') = JSON_EXTRACT('["A"]', '$[0]') vaut 0) ; face à un nombre, ou dans un calcul (doc->'$.n' + 0), elle est lue comme un nombre, une chaîne JSON l'étant sans ses guillemets, par son préfixe numérique ("9x" vaut 9).
JSON_EXTRACT#
JSON_EXTRACT(document, chemin [, chemin ...])Valeur désignée par le chemin, écrite comme un document. Avec plusieurs chemins, ou un chemin comportant un joker ou une plage, les valeurs trouvées sont réunies dans un tableau (dans l'ordre des chemins puis du document). NULL si rien n'est trouvé.
Retour : texte JSON.
SELECT JSON_EXTRACT('{"a": 1, "b": [10, 20]}', '$.b[1]'); -- '20'
SELECT JSON_EXTRACT('{"a": 1, "b": [10, 20]}', '$.a', '$.b'); -- '[1, [10, 20]]'
SELECT JSON_EXTRACT('{"x": {"p": 1}, "y": {"p": 2}}', '$**.p'); -- '[1, 2]'JSON_UNQUOTE#
JSON_UNQUOTE(texte)Si texte commence (après ses blancs) par une chaîne JSON, la rend sans ses guillemets et avec ses échappements (\", \n, é...) résolus, la suite du texte étant ignorée ('"a" x' donne a) ; un échappement inconnu vaut le caractère lui-même ('"a\\x"' donne ax) ; tout autre texte est rendu tel quel. Une chaîne JSON mal formée est rendue telle quelle, avec l'avertissement 4036, 4037 ou 4038.
SELECT JSON_UNQUOTE('"été"'), JSON_UNQUOTE('[1, 2]'); -- 'été', '[1, 2]'JSON_VALUE#
JSON_VALUE(document, chemin
[RETURNING type]
[{NULL | ERROR | DEFAULT valeur} ON EMPTY]
[{NULL | ERROR | DEFAULT valeur} ON ERROR])Valeur scalaire désignée par le chemin, sans guillemets, convertie au type de RETURNING : SIGNED, UNSIGNED, DECIMAL(p, s), DOUBLE / FLOAT / REAL, DATE, TIME, DATETIME ou CHAR(n) (par défaut CHAR(512)). Un null JSON donne NULL, un booléen 1 ou 0 ; un chemin avec joker ou plage donne NULL sans avertissement.
ON EMPTYs'applique quand le chemin ne désigne rien ;ON ERRORs'applique quand la valeur trouvée est un tableau ou un objet, ou ne se convertit pas au type demandé (texte non numérique pourSIGNED, trop de chiffres pourDECIMAL(p, s), texte plus long quenpourCHAR(n)...).
La réaction par défaut est NULL. ERROR ON EMPTY lève l'erreur 3966, ERROR ON ERROR l'erreur 3156. ON EMPTY s'écrit avant ON ERROR.
SELECT JSON_VALUE('{"prix": "12.5"}', '$.prix' RETURNING DECIMAL(6,2)); -- 12.50
SELECT JSON_VALUE('{"prix": 1}', '$.remise' DEFAULT 0 ON EMPTY); -- 0
SELECT JSON_VALUE('{"code": "A7"}', '$.code' RETURNING SIGNED DEFAULT -1 ON ERROR); -- -1JSON_SET / JSON_INSERT / JSON_REPLACE#
JSON_SET(document, chemin, valeur [, chemin, valeur ...])
JSON_INSERT(document, chemin, valeur [, chemin, valeur ...])
JSON_REPLACE(document, chemin, valeur [, chemin, valeur ...])Placent chaque valeur au chemin indiqué, les paires étant appliquées l'une après l'autre : JSON_SET remplace une valeur existante ou ajoute la valeur absente, JSON_INSERT ajoute seulement, JSON_REPLACE remplace seulement. Un membre absent est ajouté à la fin de l'objet ; un indice au-delà de la fin d'un tableau ajoute en fin ; un indice appliqué à une valeur qui n'est pas un tableau l'enveloppe (JSON_SET('{"a": 1}', '$.a[1]', 2) donne {"a": [1, 2]}). Un chemin dont le parent n'existe pas est ignoré. Les valeurs suivent les règles de conversion de JSON_OBJECT : texte entre guillemets, nombre tel quel, NULL en null, document (fonction JSON, CAST(... AS JSON), colonne JSON) imbriqué tel quel.
Retour : texte JSON (NULL si le document ou un chemin est NULL).
SELECT JSON_SET('{"a": 1}', '$.a', 2, '$.b', 'x'); -- '{"a": 2, "b": "x"}'
SELECT JSON_INSERT('{"a": 1}', '$.a', 2, '$.b', 3); -- '{"a": 1, "b": 3}'
SELECT JSON_REPLACE('{"a": 1}', '$.a', 2, '$.b', 3); -- '{"a": 2}'
UPDATE fiches SET doc = JSON_SET(doc, '$.age', doc->'$.age' + 1) WHERE id = 1;JSON_REMOVE#
JSON_REMOVE(document, chemin [, chemin ...])Retire le membre ou la case désignés (les chemins sont appliqués l'un après l'autre ; un chemin qui ne désigne rien est ignoré). Le chemin $ seul donne NULL avec l'avertissement 4051.
SELECT JSON_REMOVE('[1, 2, 3]', '$[1]'); -- '[1, 3]'JSON_ARRAY_APPEND / JSON_ARRAY_INSERT#
JSON_ARRAY_APPEND(document, chemin, valeur [, chemin, valeur ...])
JSON_ARRAY_INSERT(document, chemin, valeur [, chemin, valeur ...])JSON_ARRAY_APPEND ajoute la valeur à la fin du tableau désigné ; une valeur qui n'est pas un tableau devient un tableau [valeur, ajoutée]. JSON_ARRAY_INSERT insère la valeur à la case désignée, les suivantes étant décalées (en fin de tableau au-delà) ; son chemin doit se terminer par une case [n] (sinon erreur 3165).
SELECT JSON_ARRAY_APPEND('[1, [2]]', '$[1]', 3); -- '[1, [2, 3]]'
SELECT JSON_ARRAY_INSERT('[1, 3]', '$[1]', 2); -- '[1, 2, 3]'JSON_CONTAINS#
JSON_CONTAINS(cible, candidat [, chemin])1 si candidat est contenu dans cible (ou dans la valeur désignée par chemin), 0 sinon, NULL si le chemin ne désigne rien. Deux scalaires se contiennent s'ils sont égaux (1 et 1.0 sont égaux) ; un tableau contient un scalaire présent parmi ses éléments, et un tableau dont il contient chaque élément ; un objet contient un objet dont chaque membre existe chez lui avec une valeur qui contient la sienne.
SELECT JSON_CONTAINS('{"a": 1, "b": [1, 2]}', '[2]', '$.b'); -- 1JSON_CONTAINS_PATH#
JSON_CONTAINS_PATH(document, 'one' | 'all', chemin [, chemin ...])1 si au moins un chemin ('one') ou tous les chemins ('all') désignent une valeur. Un autre mode rend NULL avec l'avertissement 4046, avant toute lecture du document.
SELECT JSON_CONTAINS_PATH('{"a": 1, "b": 2}', 'one', '$.a', '$.z'); -- 1
SELECT JSON_CONTAINS_PATH('{"a": 1, "b": 2}', 'all', '$.a', '$.z'); -- 0JSON_KEYS#
JSON_KEYS(document [, chemin])Tableau JSON des noms de membres de l'objet (du document ou de la valeur désignée) ; NULL si ce n'est pas un objet.
SELECT JSON_KEYS('{"a": 1, "b": {"c": 2}}'); -- '["a", "b"]'JSON_LENGTH#
JSON_LENGTH(document [, chemin])Nombre d'éléments d'un tableau, de membres d'un objet, 1 pour un scalaire ; NULL si le chemin ne désigne rien.
SELECT JSON_LENGTH('[1, 2, [3, 4]]'), JSON_LENGTH('{"a": 1, "b": {"c": 2}}', '$.b'), JSON_LENGTH('7'); -- 3, 1, 1JSON_DEPTH#
JSON_DEPTH(document)Profondeur d'imbrication : 1 pour un scalaire, un tableau ou un objet vides, 1 + la profondeur du plus profond élément sinon.
SELECT JSON_DEPTH('[]'), JSON_DEPTH('[1, [2]]'), JSON_DEPTH('{"a": {"b": 1}}'); -- 1, 3, 3JSON_TYPE#
JSON_TYPE(document)Type de la valeur : OBJECT, ARRAY, STRING, INTEGER, UNSIGNED INTEGER (entier au-delà de BIGINT), DOUBLE (nombre écrit avec une partie décimale ou un exposant), BOOLEAN ou NULL. Un texte qui n'est pas du JSON (JSON_TYPE('abc')) donne NULL avec l'avertissement 4038.
SELECT JSON_TYPE(JSON_EXTRACT('{"a": [1]}', '$.a')); -- ARRAYJSON_SEARCH#
JSON_SEARCH(document, 'one' | 'all', motif [, echappement [, chemin ...]])Chemin des scalaires du document (ou des valeurs désignées par les chemins) dont le texte vérifie le motif LIKE (chaînes, mais aussi nombres tels qu'écrits, true, false et null) (%, _, caractère d'échappement \ par défaut ou echappement s'il est donné ; comparaison de LIKE sous l'interclassement du document : binaire pour une colonne JSON (sensible à la casse), utf8mb4_general_ci pour un littéral (sans casse ni accents), celui de la colonne pour une colonne texte). 'one' rend le premier trouvé, 'all' tous : une chaîne JSON pour un résultat, un tableau pour plusieurs, NULL si rien n'est trouvé. Un nom de membre y est écrit sous son texte écrit, sans guillemets ($.a b, $.\u00e9). Un caractère d'échappement de plus d'un caractère lève l'erreur 1210 ; un autre mode que 'one' / 'all' rend NULL avec l'avertissement 4046.
SELECT JSON_SEARCH('["abc", {"x": "abc"}]', 'all', 'ab%'); -- '["$[0]", "$[1].x"]'JSON_OVERLAPS#
JSON_OVERLAPS(document1, document2)1 si les deux documents ont une partie commune : un élément commun à deux tableaux, un membre commun (même nom, même valeur) à deux objets, deux scalaires égaux ; une valeur isolée face à un tableau est traitée comme l'un de ses éléments.
SELECT JSON_OVERLAPS('[1, 3, 5]', '[2, 5]'), JSON_OVERLAPS('{"a": 1}', '{"a": 2}'); -- 1, 0MEMBER OF#
valeur MEMBER OF (document)1 si valeur (convertie comme un argument de JSON_ARRAY) est un élément du tableau document, ou égale au document s'il n'est pas un tableau. NULL si l'un des deux est NULL.
SELECT 2 MEMBER OF ('[1, 2]'), 'a' MEMBER OF ('["a", "b"]'); -- 1, 1JSON_PRETTY#
JSON_PRETTY(document [, indentation])Synonyme de JSON_DETAILED (quatre espaces par niveau par défaut) : voir JSON_COMPACT / JSON_LOOSE / JSON_DETAILED.
SELECT JSON_PRETTY('{"a":[1,2]}', 2);
-- {
-- "a":
-- [
-- 1,
-- 2
-- ]
-- }JSON_QUERY#
JSON_QUERY(document, chemin)Objet ou tableau désigné par le chemin, tel qu'écrit dans le document (espaces compris) ; NULL pour un scalaire, un chemin qui ne désigne rien ou qui contient un joker ou une plage (sans avertissement). Pendant de JSON_VALUE, qui ne rend que les scalaires.
SELECT JSON_QUERY('{"a": {"b": [1, 2]}, "c": 3}', '$.a'), -- '{"b": [1, 2]}'
JSON_QUERY('{"a": {"b": [1, 2]}, "c": 3}', '$.c'), -- NULL
JSON_QUERY('{"a": [1 ,2]}', '$.a'); -- '[1 ,2]'JSON_EXISTS#
JSON_EXISTS(document, chemin)1 si le chemin désigne une valeur (même un null JSON), 0 sinon, sans jamais d'avertissement : un chemin invalide donne NULL ; un document invalide est parcouru jusqu'à son erreur, et la fonction rend 1 si la valeur désignée a été atteinte avant (un membre dès son nom et son : lus, un élément dès sa place ouverte), NULL sinon : JSON_EXISTS('{"a": 1, }', '$.a') vaut 1, JSON_EXISTS('{', '$') aussi.
SELECT JSON_EXISTS('{"a": null}', '$.a'), JSON_EXISTS('{"a": 1}', '$.b'); -- 1, 0JSON_EQUALS#
JSON_EQUALS(document1, document2)1 si les deux documents sont égaux : nombres comparés par leur valeur (1 = 1.0), membres d'objets sans égard à leur ordre, éléments de tableaux dans leur ordre.
SELECT JSON_EQUALS('{"a": 1, "b": 2}', '{"b": 2, "a": 1}'), JSON_EQUALS('[1, 2]', '[2, 1]'); -- 1, 0JSON_NORMALIZE#
JSON_NORMALIZE(document)Forme canonique du document, pour comparer ou indexer : membres rangés par nom, nombres en notation scientifique, aucune espace. Deux documents égaux au sens de JSON_EQUALS ont la même forme normalisée.
SELECT JSON_NORMALIZE('{"b": 15, "a": [0.5]}'); -- '{"a":[5.0E-1],"b":1.5E1}'JSON_COMPACT / JSON_LOOSE / JSON_DETAILED#
JSON_COMPACT(document)
JSON_LOOSE(document)
JSON_DETAILED(document [, indentation])Réécriture du document : JSON_COMPACT sans aucune espace ({"a":[1,2]}), JSON_LOOSE avec une espace après chaque virgule et chaque deux-points ({"a": [1, 2]}, l'écriture habituelle de MIRAJ), JSON_DETAILED (et son synonyme JSON_PRETTY) sur plusieurs lignes, avec indentation espaces par niveau (4 par défaut, de 0 à 8 : une valeur plus grande vaut 8, une valeur négative 0) : un élément ou un membre par ligne ; un tableau d'un seul scalaire et un tableau vide restent sur une ligne (["a"], []) ; un objet vide s'écrit { puis } à la ligne ; la valeur tableau ou objet d'un membre passe à la ligne suivante, au niveau du nom.
SELECT JSON_DETAILED('{"a": [1, 2], "b": ["x"], "c": {}}');
-- {
-- "a":
-- [
-- 1,
-- 2
-- ],
-- "b":
-- ["x"],
-- "c":
-- {
-- }
-- }JSON_ARRAY_INTERSECT#
JSON_ARRAY_INTERSECT(tableau1, tableau2)Éléments de tableau2 présents dans tableau1, dans l'ordre du second ; chaque élément du premier ne sert qu'une fois. NULL si l'un des documents n'est pas un tableau ou si rien n'est commun.
SELECT JSON_ARRAY_INTERSECT('[1, 2, 2, 3]', '[2, 3, 2]'); -- '[2, 3, 2]'
SELECT JSON_ARRAY_INTERSECT('[1, 2, 3]', '[3, 1]'); -- '[3, 1]'JSON_OBJECT_FILTER_KEYS#
JSON_OBJECT_FILTER_KEYS(objet, tableau_de_cles)Membres de l'objet dont le nom figure dans le tableau de chaînes. NULL si le premier document n'est pas un objet, le second pas un tableau, ou si aucun nom n'est commun.
SELECT JSON_OBJECT_FILTER_KEYS('{"a": 1, "b": 2, "c": 3}', '["a", "c", "z"]'); -- '{"a": 1, "c": 3}'JSON_OBJECT_TO_ARRAY#
JSON_OBJECT_TO_ARRAY(objet)L'objet en tableau de paires [nom, valeur] ; NULL pour un document qui n'est pas un objet.
SELECT JSON_OBJECT_TO_ARRAY('{"a": 1, "b": [2]}'); -- '[["a", 1], ["b", [2]]]'JSON_KEY_VALUE#
JSON_KEY_VALUE(document, chemin)L'objet désigné par le chemin en tableau de {"key": nom, "value": valeur}, pratique avec JSON_TABLE pour parcourir des membres de noms inconnus ; NULL si le chemin ne désigne pas un objet.
SELECT JSON_KEY_VALUE('{"a": 1, "b": [2]}', '$');
-- '[{"key": "a", "value": 1}, {"key": "b", "value": [2]}]'
SELECT jt.k, jt.v
FROM JSON_TABLE(JSON_KEY_VALUE('{"a": 1, "b": 2}', '$'), '$[*]'
COLUMNS (k VARCHAR(10) PATH '$.key', v INT PATH '$.value')) AS jt;
-- 'a', 1
-- 'b', 2JSON_SCHEMA_VALID / JSON_SCHEMA_VALIDATION_REPORT#
JSON_SCHEMA_VALID(schema, document)
JSON_SCHEMA_VALIDATION_REPORT(schema, document)Validation d'un document par un schéma JSON Schema (brouillon 4 et mots-clés compatibles des suivants). JSON_SCHEMA_VALID rend 1 si le document est conforme, 0 sinon ; JSON_SCHEMA_VALIDATION_REPORT rend {"valid": true} ou le premier manquement relevé : raison, emplacement dans le schéma et dans le document (pointeurs JSON #/...) et mot-clé non respecté.
Mots-clés pris en compte : type, enum, const, minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, minLength, maxLength, pattern, items, additionalItems, minItems, maxItems, uniqueItems, contains, properties, patternProperties, additionalProperties, required, minProperties, maxProperties, dependencies, propertyNames, allOf, anyOf, oneOf, not, if / then / else, schémas true / false et $ref interne (#/definitions/nom). Les autres (format, title...) sont ignorés. JSON_SCHEMA_VALID rend 1 pour un schéma qui n'est pas un objet, NULL pour un schéma invalide et 0 pour un document invalide (avertissement 4037 / 4038) ; une valeur de type autre que object, array, string, number, boolean ou null, où qu'elle soit dans le schéma, lève l'erreur 4193 — integer compris (écrire number, avec multipleOf: 1 au besoin). JSON_SCHEMA_VALIDATION_REPORT exige un objet (erreur 3853) et admet integer. Dans JSON_SCHEMA_VALID, pour propertyNames, seul un pattern placé directement dans son schéma s'applique au nom de chaque membre, les autres mots-clés (maxLength, minLength, type, enum, not…) à la valeur du membre ({"propertyNames": {"maxLength": 2}} accepte {"abc": 1} et refuse {"a": "abc"}), et un schéma true / false lève 4193 ; JSON_SCHEMA_VALIDATION_REPORT applique tout le schéma au nom. Un pattern invalide lève 1139. Chaînes et noms de membres sont pris sous leur texte écrit (voir échappements) : pattern s'applique à ce texte, minLength / maxLength en comptent les octets ("é" en vaut 2).
CREATE TABLE lieux (
doc JSON,
CHECK (JSON_SCHEMA_VALID('{"type": "object", "required": ["lat", "lon"],
"properties": {"lat": {"type": "number", "minimum": -90, "maximum": 90}}}', doc))
);
SELECT JSON_SCHEMA_VALIDATION_REPORT('{"properties": {"lat": {"maximum": 90}}}', '{"lat": 91}');
-- '{"valid": false, "reason": "The JSON document location '#/lat' failed requirement 'maximum' at JSON Schema location '#/properties/lat'",
-- "schema-location": "#/properties/lat", "document-location": "#/lat", "schema-failed-keyword": "maximum"}'
SELECT JSON_SCHEMA_VALID('{"type": "object", "required": ["lat"]}', '{"lon": 1}'); -- 0JSON_TABLE#
SELECT ... FROM JSON_TABLE(document, 'chemin' COLUMNS (
nom FOR ORDINALITY,
nom type PATH 'chemin' [reaction ON EMPTY] [reaction ON ERROR],
nom type EXISTS PATH 'chemin',
NESTED [PATH] 'chemin' COLUMNS (...)
)) [AS] alias
-- reaction : NULL | ERROR | DEFAULT 'texte JSON'Source de table du FROM : une ligne par valeur que le chemin désigne dans le document ('$[*]' pour chaque élément d'un tableau). L'alias est obligatoire (erreur 4177 sans lui). Un document NULL, ou un chemin qui ne désigne rien, ne donne aucune ligne ; un texte qui n'est pas un document lève 4037 ou 4038, un chemin invalide 4041 ou 4042 (des erreurs ici).
Le document peut être un littéral, une variable, un paramètre de routine ou une expression sur les colonnes des tables qui précèdent dans le FROM : la table est alors recalculée pour chaque ligne de ces tables (jointure latérale). Il s'écrit après une virgule, CROSS JOIN, [INNER] JOIN ... ON ou LEFT JOIN ... ON ; avec LEFT JOIN, une ligne dont le document ne donne aucune ligne (ou aucune qui satisfait ON) est gardée, complétée de NULL. Une référence latérale dans un RIGHT JOIN lève 3668, une colonne d'une table qui suit le JSON_TABLE 1054 ; le document ne peut contenir ni sous-requête ni agrégat (1210).
Colonnes (noms uniques, tous niveaux confondus, sinon 1060) :
nom FOR ORDINALITY: rang de la ligne dans son niveau, à partir de 1 (INT UNSIGNED) ;nom type PATH 'chemin': valeur désignée, relative à la ligne, convertie au type déclaré comme à l'écriture dans une colonne de ce type (VARCHAR(n),INT,DECIMAL(p,s),DATE...) hors mode strict, quel que soit lesql_mode: une valeur hors limites est ramenée à la borne (avertissement 1264), un texte trop long tronqué (1265), une valeur qui ne se convertit pas mise à zéro (1366, colonne citée`*any*`.`json_table`.`nom`). Une colonneJSONreçoit le document désigné tel qu'il est écrit dans le texte source, espaces compris. UnnullJSON donne NULL ;nom type EXISTS PATH 'chemin': 1 si le chemin désigne une valeur, 0 sinon ;NESTED [PATH] 'chemin' COLUMNS (...): une ligne par valeur désignée dans la valeur de la ligne parente, combinée avec les colonnes du parent ; sans aucune valeur, la ligne du parent reste, colonnes imbriquées à NULL. DeuxNESTEDau même niveau produisent leurs lignes l'un après l'autre, les colonnes de l'autre à NULL.
ON EMPTY s'applique quand le chemin ne désigne rien (ERROR : 4176) ; ON ERROR quand la valeur est un tableau ou un objet destiné à une colonne scalaire (ERROR : 4178) ou quand le chemin désigne plusieurs valeurs, même pour une colonne JSON (ERROR : 4179) ; ces trois erreurs citent la colonne et l'alias. Une valeur qui ne se convertit pas au type ne relève pas de ON ERROR (voir ci-dessus). Les deux réagissent par NULL par défaut. La valeur de DEFAULT est un texte placé dans la colonne comme une valeur trouvée, avec les mêmes conversions : DEFAULT 'texte' donne texte, DEFAULT '"texte"' garde ses guillemets, DEFAULT 'abc' dans une colonne INT donne 0 et l'avertissement 1366. ON ERROR peut précéder ON EMPTY.
CREATE TABLE cmd (id INT PRIMARY KEY, date_cmd DATE, lignes JSON);
INSERT INTO cmd VALUES
(1, '2026-02-01', '[{"article": "A1", "qte": 2, "options": ["rouge", "XL"]}, {"article": "B7"}]'),
(2, '2026-03-05', '[]');
SELECT c.id, l.art, l.q, l.opt
FROM cmd c
LEFT JOIN JSON_TABLE(c.lignes, '$[*]' COLUMNS (
n FOR ORDINALITY,
art VARCHAR(10) PATH '$.article',
q INT PATH '$.qte' DEFAULT '1' ON EMPTY,
NESTED PATH '$.options[*]' COLUMNS (opt VARCHAR(20) PATH '$')
)) AS l ON TRUE
WHERE c.date_cmd >= '2026-01-01'
ORDER BY c.id, l.n;
-- id | art | q | opt
-- 1 | A1 | 2 | rouge
-- 1 | A1 | 2 | XL
-- 1 | B7 | 1 | NULL
-- 2 | NULL | NULL | NULLJSON_TABLE s'emploie comme toute table : WHERE, GROUP BY, ORDER BY, table dérivée, sous-requête (corrélée ou non), vue (SHOW CREATE VIEW rend le texte écrit), INSERT ... SELECT, CREATE TABLE ... AS SELECT. EXPLAIN le montre comme une ligne Table function: json_table. La table est calculée en mémoire, sans index : filtrer d'abord les lignes des tables qui la précèdent.
10.11 Fonctions vectorielles (VECTOR(n))#
Ces fonctions opèrent sur le type VECTOR(n) (n flottants 32 bits), utilisé pour la recherche par similarité (embeddings). Elles se répartissent en trois familles aux conventions d'erreur différentes :
- Famille
VEC_*: un argument incorrect (mauvais format, dimensions différentes) rendNULLplutôt que d'échouer. - Famille
STRING_TO_VECTOR/VECTOR_TO_STRING/VECTOR_DIM/DISTANCE: un argument incorrect lève une erreur. - Famille
L2_DISTANCE,COSINE_DISTANCE,VECTOR_ADD, etc. (et les opérateurs<->,<=>,<#>,<+>,+,-,*entre vecteurs, voir le chapitre 6. Types de données) : un argument incorrect lève une erreur ; les calculs se font en simple précision (32 bits).
Partout, un argument vecteur accepte aussi sa forme texte '[1, 2, 3]'.
Récapitulatif :
| Fonction | Signature |
|---|---|
| VEC_FROMTEXT | VEC_FROMTEXT(chaine) |
| VEC_TOTEXT | VEC_TOTEXT(vecteur) |
| VEC_DISTANCE_EUCLIDEAN | VEC_DISTANCE_EUCLIDEAN(vecteur1, vecteur2) |
| VEC_DISTANCE_COSINE | VEC_DISTANCE_COSINE(vecteur1, vecteur2) |
| VEC_DISTANCE | VEC_DISTANCE(vecteur1, vecteur2) |
| STRING_TO_VECTOR / TO_VECTOR | STRING_TO_VECTOR(chaine) |
| VECTOR_TO_STRING / FROM_VECTOR | VECTOR_TO_STRING(vecteur) |
| VECTOR_DIM | VECTOR_DIM(vecteur) |
| DISTANCE | DISTANCE(vecteur1, vecteur2, metrique) |
| L2_DISTANCE | L2_DISTANCE(vecteur1, vecteur2) |
| COSINE_DISTANCE | COSINE_DISTANCE(vecteur1, vecteur2) |
| INNER_PRODUCT | INNER_PRODUCT(vecteur1, vecteur2) |
| VECTOR_NEGATIVE_INNER_PRODUCT | VECTOR_NEGATIVE_INNER_PRODUCT(vecteur1, vecteur2) |
| L1_DISTANCE | L1_DISTANCE(vecteur1, vecteur2) |
| VECTOR_DIMS | VECTOR_DIMS(vecteur) |
| VECTOR_NORM | VECTOR_NORM(vecteur) |
| L2_NORMALIZE | L2_NORMALIZE(vecteur) |
| SUBVECTOR | SUBVECTOR(vecteur, position, nombre) |
| VECTOR_ADD | VECTOR_ADD(vecteur1, vecteur2) |
| VECTOR_SUB | VECTOR_SUB(vecteur1, vecteur2) |
| VECTOR_MUL | VECTOR_MUL(vecteur1, vecteur2) |
VEC_FROMTEXT#
VEC_FROMTEXT(chaine)Convertit la forme texte '[1, 2, 3]' en vecteur binaire. NULL si chaine n'est pas un vecteur texte valide. '[]' donne un vecteur vide. Des composantes dont la somme des carrés déborde en flottant 32 bits donnent NULL avec l'avertissement 1292 Truncated incorrect vector value: '…'.
Retour : VECTOR(n).
SELECT HEX(VEC_FROMTEXT('[1, 2]')); -- '0000803F00000040' (deux flottants 32 bits)
SELECT VEC_FROMTEXT('[1, x]'); -- NULL
SELECT VEC_FROMTEXT('[1e20]') IS NULL; -- 1, avertissement 1292VEC_TOTEXT#
VEC_TOTEXT(vecteur)Forme texte d'un vecteur, avec six chiffres significatifs par composante.
Retour : texte.
SELECT VEC_TOTEXT(VEC_FROMTEXT('[1, 2.5, 0.333333333]')); -- '[1,2.5,0.333333]'VEC_DISTANCE_EUCLIDEAN#
VEC_DISTANCE_EUCLIDEAN(vecteur1, vecteur2)Distance euclidienne (L2) entre deux vecteurs, calculée en double précision. NULL si un argument est invalide ou si les dimensions diffèrent.
Retour : DOUBLE.
SELECT VEC_DISTANCE_EUCLIDEAN('[0, 0]', '[3, 4]'); -- 5.0
SELECT VEC_DISTANCE_EUCLIDEAN('[0, 0]', '[3, 4, 5]'); -- NULLVEC_DISTANCE_COSINE#
VEC_DISTANCE_COSINE(vecteur1, vecteur2)Distance cosinus (1 - similarité cosinus) entre deux vecteurs, en double précision.
SELECT VEC_DISTANCE_COSINE('[1, 0]', '[0, 1]'), VEC_DISTANCE_COSINE('[1, 1]', '[2, 2]'); -- 1.0, 0.0VEC_DISTANCE#
VEC_DISTANCE(vecteur1, vecteur2)Distance de la métrique de l'index vectoriel que porte l'une des deux colonnes passées en argument (euclidienne, cosinus ou produit scalaire négé, voir le chapitre 11). Refusé à la compilation (erreur 4206) en dehors d'un contexte avec index vectoriel, la distance n'étant alors jamais définie sans indication de métrique.
CREATE TABLE emb (id INT PRIMARY KEY, v VECTOR(2) NOT NULL, VECTOR INDEX (v) DISTANCE=cosine);
INSERT INTO emb VALUES (1, VEC_FROMTEXT('[1, 0]')), (2, VEC_FROMTEXT('[1, 1]'));
SELECT id, VEC_DISTANCE(v, VEC_FROMTEXT('[0, 1]')) AS d FROM emb ORDER BY d;
-- 2, 0.29289321881345254
-- 1, 1.0
SELECT VEC_DISTANCE('[0, 0]', '[3, 4]'); -- erreur 4206 (aucun index)STRING_TO_VECTOR / TO_VECTOR#
STRING_TO_VECTOR(chaine)Convertit chaine (forme texte '[1, 2, 3]') en vecteur binaire ; lève une erreur si chaine n'est pas valide (au lieu de rendre NULL, contrairement à VEC_FROMTEXT). TO_VECTOR est un alias strict.
SELECT HEX(STRING_TO_VECTOR('[1, 2]')); -- '0000803F00000040'
SELECT STRING_TO_VECTOR('[1, x]'); -- erreur 6138 (Data cannot be converted to a valid vector)VECTOR_TO_STRING / FROM_VECTOR#
VECTOR_TO_STRING(vecteur)Forme texte d'un vecteur (notation exponentielle, cinq chiffres significatifs). FROM_VECTOR est un alias strict.
SELECT VECTOR_TO_STRING(STRING_TO_VECTOR('[1, 2.5]')); -- '[1.00000e+00,2.50000e+00]'VECTOR_DIM#
VECTOR_DIM(vecteur)Nombre de composantes du vecteur.
Retour : BIGINT.
SELECT VECTOR_DIM('[1, 2, 3]'); -- 3DISTANCE#
DISTANCE(vecteur1, vecteur2, metrique)Distance entre deux vecteurs selon metrique : 'EUCLIDEAN', 'COSINE' ou 'DOT' (produit scalaire). Erreur si metrique n'est pas reconnue.
Retour : DOUBLE.
SELECT DISTANCE('[0, 0]', '[3, 4]', 'EUCLIDEAN'), DISTANCE('[1, 0]', '[0, 1]', 'COSINE'), DISTANCE('[1, 2]', '[3, 4]', 'DOT');
-- 5.0, 1.0, 11.0
SELECT DISTANCE('[1, 2]', '[3, 4]', 'XX'); -- erreur 1210L2_DISTANCE#
L2_DISTANCE(vecteur1, vecteur2)Distance euclidienne, calculs en simple précision (32 bits). Erreur si les dimensions diffèrent (message donnant les deux dimensions).
SELECT L2_DISTANCE('[0, 0]', '[3, 4]'); -- 5.0
SELECT L2_DISTANCE('[0, 0]', '[3, 4, 5]'); -- erreur 7600 (different vector dimensions 2 and 3)COSINE_DISTANCE#
COSINE_DISTANCE(vecteur1, vecteur2)Distance cosinus, calculs en simple précision.
SELECT COSINE_DISTANCE('[1, 0]', '[0, 1]'); -- 1.0INNER_PRODUCT#
INNER_PRODUCT(vecteur1, vecteur2)Produit scalaire des deux vecteurs.
SELECT INNER_PRODUCT('[1, 2]', '[3, 4]'); -- 11.0VECTOR_NEGATIVE_INNER_PRODUCT#
VECTOR_NEGATIVE_INNER_PRODUCT(vecteur1, vecteur2)Opposé du produit scalaire (utile pour trier par similarité décroissante avec un index qui minimise).
SELECT VECTOR_NEGATIVE_INNER_PRODUCT('[1, 2]', '[3, 4]'); -- -11.0L1_DISTANCE#
L1_DISTANCE(vecteur1, vecteur2)Distance de Manhattan (somme des valeurs absolues des différences composante par composante).
SELECT L1_DISTANCE('[0, 0]', '[3, 4]'); -- 7.0VECTOR_DIMS#
VECTOR_DIMS(vecteur)Nombre de composantes (variante de VECTOR_DIM de la famille « opérateur », qui lève une erreur plutôt que de rendre NULL sur un argument incorrect).
SELECT VECTOR_DIMS('[1, 2, 3]'); -- 3VECTOR_NORM#
VECTOR_NORM(vecteur)Norme euclidienne (longueur) du vecteur.
Retour : DOUBLE.
SELECT VECTOR_NORM('[3, 4]'); -- 5.0L2_NORMALIZE#
L2_NORMALIZE(vecteur)Vecteur ramené à une norme de 1 (chaque composante divisée par la norme) ; un vecteur nul est rendu inchangé. Erreur en cas de dépassement de capacité d'un flottant 32 bits.
Retour : VECTOR(n).
SELECT VECTOR_TO_STRING(L2_NORMALIZE('[3, 4]')); -- '[6.00000e-01,8.00000e-01]'
SELECT VECTOR_TO_STRING(L2_NORMALIZE('[0, 0]')); -- '[0.00000e+00,0.00000e+00]'SUBVECTOR#
SUBVECTOR(vecteur, position, nombre)Sous-vecteur de nombre composantes à partir de position (base 1, comme SUBSTRING). Erreur si nombre < 1 ou si la plage demandée est vide.
SELECT VECTOR_TO_STRING(SUBVECTOR('[1, 2, 3, 4]', 2, 2)); -- '[2.00000e+00,3.00000e+00]'VECTOR_ADD#
VECTOR_ADD(vecteur1, vecteur2)Addition élément par élément. Erreur en cas de dépassement de capacité.
SELECT VEC_TOTEXT(VECTOR_ADD('[1, 2]', '[3, 4]')); -- '[4,6]'VECTOR_SUB#
VECTOR_SUB(vecteur1, vecteur2)Soustraction élément par élément.
SELECT VEC_TOTEXT(VECTOR_SUB('[1, 2]', '[3, 4]')); -- '[-2,-2]'VECTOR_MUL#
VECTOR_MUL(vecteur1, vecteur2)Multiplication élément par élément. Erreur aussi en cas de perte de précision par soupassement (résultat à zéro alors qu'aucun des deux facteurs ne l'était).
SELECT VEC_TOTEXT(VECTOR_MUL('[1, 2]', '[3, 4]')); -- '[3,8]'10.12 Mise en forme avancée#
Récapitulatif :
| Fonction | Signature |
|---|---|
| SFORMAT | SFORMAT(format [, arg1, arg2, ...]) |
SFORMAT#
SFORMAT(format [, arg1, arg2, ...])Met en forme arg1, arg2, ... selon format, à la manière de la bibliothèque C++ {fmt} (syntaxe proche de str.format() de Python). Les champs {} prennent les arguments dans l'ordre ; {n} prend l'argument d'indice n (base 0) — les deux numérotations ne peuvent pas être mélangées dans un même appel. {{ et }} produisent une accolade littérale.
Spécification après : (facultative) : [[remplissage]alignement][signe][#][0][largeur][.précision][L][type], où largeur et précision peuvent eux-mêmes venir d'un argument entier ({:{}}, {:.{2}}). Types acceptés selon la nature de l'argument : d x X o b B c pour un entier ; e E f F g G a A pour un nombre à virgule ; s ? pour un texte ; sans type, la forme la plus courte qui redonne le même nombre en le relisant. L groupe les chiffres de milliers par ,, en base dix seulement (sans effet avec x, o, b). Autres règles, comme la référence :
#sans type (ou avecg) écrit une décimale nulle plutôt qu'un point seul (SFORMAT('{:#}', 123e0):'123.0') ;a/Aécrit zéro0x0p+0et arrondit la précision au plus proche, moitié vers le chiffre pair ;- la précision d'un texte compte des caractères (elle est ignorée par
?), et sa largeur des colonnes d'affichage (un idéogramme ou un émoji compte double) ; - le drapeau
0suivi d'un alignement explicite ne remplace que le remplissage (SFORMAT('{:<05}', -5):'-5000') ;{:00}est admis (le second0commence la largeur), et}peut servir de caractère de remplissage ({:}<5}).
Comportement avec NULL : un argument numérique NULL est traité comme 0 ; un argument texte NULL, ou le format lui-même NULL, rendent NULL pour tout l'appel. Toute erreur de format (spécification invalide, argument absent, accolade non appariée, changement de numérotation en cours de format) rend aussi NULL, plutôt que de lever une erreur — de même qu'un résultat qui dépasserait max_allowed_packet.
Retour : texte.
SELECT SFORMAT('{} vaut {:.2f} ({:#x})', 'Pi', 3.14159, 255);
-- 'Pi vaut 3.14 (0xff)'
SELECT SFORMAT('{0} puis {1} puis {0}', 'A', 'B');
-- 'A puis B puis A'
SELECT SFORMAT('{:L}', 1234567);
-- '1,234,567' (le type 'L' groupe les milliers)10.13 Fonctions de fenêtrage#
Une fonction de fenêtrage calcule une valeur pour chaque ligne en regardant les autres lignes de sa partition, sans les regrouper (contrairement à GROUP BY). Elle s'écrit :
fonction(...) OVER ([PARTITION BY expr, ...] [ORDER BY expr [ASC|DESC], ...] [cadre])PARTITION BYdécoupe les lignes en partitions indépendantes ; sans lui, toutes les lignes forment une seule partition.ORDER BYfixe l'ordre des lignes dans la partition. Les lignes qui ont la même valeur de clé sont des ex æquo (« peers »).- Cadre :
ROWSouRANGE, sous la formeROWS débutouROWS BETWEEN début AND fin, avec les bornesUNBOUNDED PRECEDING,n PRECEDING,CURRENT ROW,n FOLLOWING,UNBOUNDED FOLLOWING.ROWSaccepte toutes les bornes ; sousRANGE, les ex æquo de la ligne courante font partie du cadre, et un décalage (n PRECEDING/n FOLLOWINGsur une clé numérique,INTERVAL n unité PRECEDING/FOLLOWINGsur une date) porte sur la valeur de l'unique clé de tri (erreurs 4019 et 4021, voir le chapitre 9, §9.18). Une fenêtre peut être nommée par la clauseWINDOWet reprise parOVER nom(§9.18). Un débutUNBOUNDED FOLLOWINGest une erreur de syntaxe (1064). - Cadre par défaut (aucun cadre écrit) : avec
ORDER BY, du début de la partition à la ligne courante et ses ex æquo (RANGE UNBOUNDED PRECEDING) ; sansORDER BY, la partition entière. - La fenêtre est évaluée après
WHERE,GROUP BYetHAVING(elle peut donc porter sur des agrégats :SUM(SUM(x)) OVER (ORDER BY g)) et avantORDER BY/LIMITde la requête ; un filtre sur son résultat s'écrit dans la clauseQUALIFYou dans une requête englobante (table dérivée), voir 9.18. Elle peut aussi figurer dans unORDER BY. - Erreurs communes : fonction de fenêtrage dans un
WHEREou imbriquée dans une autre fonction de fenêtrage/agrégat (1111) ; nombre d'arguments incorrect (1582) ; fonction scalaire ordinaire suivie deOVER(par exempleUPPER(x) OVER (...)) ouDISTINCTdans une fonction de fenêtrage (1235, « non supporté »).
| Fonction | Signature | Retour |
|---|---|---|
| ROW_NUMBER | ROW_NUMBER() | BIGINT |
| RANK | RANK() | BIGINT |
| DENSE_RANK | DENSE_RANK() | BIGINT |
| PERCENT_RANK | PERCENT_RANK() | DOUBLE |
| CUME_DIST | CUME_DIST() | DOUBLE |
| NTILE | NTILE(n) | BIGINT |
| LAG / LEAD | LAG(expr [, décalage [, défaut]]) | type de expr |
| FIRST_VALUE / LAST_VALUE | FIRST_VALUE(expr) | type de expr |
| NTH_VALUE | NTH_VALUE(expr, n) | type de expr |
| MEDIAN / PERCENTILE_CONT / PERCENTILE_DISC | MEDIAN(expr) OVER (...) <br> PERCENTILE_CONT(fraction) WITHIN GROUP (ORDER BY expr) OVER (...) | DOUBLE ou type de expr |
| Agrégats en fenêtre | SUM(expr) OVER (...) | type de l'agrégat |
Les exemples de cette section utilisent la table suivante :
CREATE TABLE T (id INT PRIMARY KEY, g CHAR(1), d INT, v INT);
INSERT INTO T VALUES (1,'a',1,10), (2,'a',2,20), (3,'a',2,30), (4,'b',3,40),
(5,'b',1,NULL), (6,'b',4,60), (7,'b',2,70);ROW_NUMBER#
ROW_NUMBER() OVER (...)Numéro de la ligne dans sa partition, à partir de 1, selon l'ORDER BY de la fenêtre. Les ex æquo reçoivent des numéros distincts (dans leur ordre de lecture, non garanti). Aucun argument (sinon erreur 1582).
SELECT id, g, d, ROW_NUMBER() OVER (PARTITION BY g ORDER BY d, id) AS rn FROM T ORDER BY id;
-- id | g | d | rn
-- 1 | a | 1 | 1
-- 2 | a | 2 | 2
-- 3 | a | 2 | 3
-- 4 | b | 3 | 3
-- 5 | b | 1 | 1
-- 6 | b | 4 | 4
-- 7 | b | 2 | 2RANK#
RANK() OVER (...)Rang de la ligne : 1 + nombre de lignes strictement précédentes. Les ex æquo partagent le même rang et le rang suivant est sauté (1, 2, 2, 4). Sans ORDER BY, toutes les lignes valent 1.
DENSE_RANK#
DENSE_RANK() OVER (...)Comme RANK mais sans trou : 1, 2, 2, 3.
SELECT id, d, RANK() OVER (ORDER BY d), DENSE_RANK() OVER (ORDER BY d)
FROM T WHERE g = 'a' OR id = 6 ORDER BY id;
-- id | d | RANK | DENSE_RANK
-- 1 | 1 | 1 | 1
-- 2 | 2 | 2 | 2
-- 3 | 2 | 2 | 2
-- 6 | 4 | 4 | 3PERCENT_RANK#
PERCENT_RANK() OVER (...)(rang - 1) / (nombre de lignes de la partition - 1), entre 0 et 1. Vaut 0 pour une partition d'une seule ligne. Retour : DOUBLE.
SELECT id, d, PERCENT_RANK() OVER (ORDER BY d) FROM T WHERE g = 'a' OR id = 6 ORDER BY id;
-- 1, 1, 0.0
-- 2, 2, 0.3333333333333333
-- 3, 2, 0.3333333333333333
-- 6, 4, 1.0CUME_DIST#
CUME_DIST() OVER (...)Distribution cumulée : nombre de lignes jusqu'à la dernière ex æquo de la ligne courante, divisé par la taille de la partition (dans ]0, 1]). Retour : DOUBLE.
SELECT id, d, CUME_DIST() OVER (ORDER BY d) FROM T WHERE g = 'a' OR id = 6 ORDER BY id;
-- 1, 1, 0.25
-- 2, 2, 0.75
-- 3, 2, 0.75
-- 6, 4, 1.0NTILE#
NTILE(n) OVER (...)Répartit la partition ordonnée en n tranches de taille aussi égale que possible et rend le numéro (à partir de 1) de la tranche de la ligne ; quand la division ne tombe pas juste, les premières tranches reçoivent une ligne de plus. n doit être un entier constant supérieur ou égal à 1 : NTILE(0), NTILE(NULL) ou une valeur non constante (colonne) rendent l'erreur 1210.
SELECT id, NTILE(3) OVER (ORDER BY id) FROM T ORDER BY id; -- tranches des 7 lignes : 1, 1, 1, 2, 2, 3, 3LAG / LEAD#
LAG(expr [, décalage [, défaut]]) OVER (...)
LEAD(expr [, décalage [, défaut]]) OVER (...)Valeur de expr dans la ligne située décalage lignes avant (LAG) ou après (LEAD) la ligne courante dans la partition ordonnée. décalage vaut 1 par défaut ; c'est un entier constant supérieur ou égal à 0 (0 désigne la ligne courante ; valeur négative, NULL ou non constante : erreur 1210). Hors de la partition, le résultat est défaut (converti au type du résultat), ou NULL s'il est omis. Le cadre de la fenêtre est sans effet sur ces fonctions. Une valeur NULL de expr dans la ligne visée est rendue telle quelle. Trois arguments au plus (sinon 1582).
SELECT id, v, LAG(v) OVER (ORDER BY id), LEAD(v, 1, -1) OVER (ORDER BY id) FROM T WHERE g = 'a' ORDER BY id;
-- 1, 10, NULL, 20
-- 2, 20, 10, 30
-- 3, 30, 20, -1FIRST_VALUE / LAST_VALUE#
FIRST_VALUE(expr) OVER (...)
LAST_VALUE(expr) OVER (...)Valeur de expr dans la première, respectivement la dernière, ligne du cadre. Attention : avec le cadre par défaut (terminé à la ligne courante et ses ex æquo), LAST_VALUE rend la valeur de la dernière ex æquo de la ligne courante ; pour obtenir la dernière ligne de la partition, écrire ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING. NULL si le cadre est vide. Une valeur NULL n'est pas ignorée.
SELECT id, g,
FIRST_VALUE(id) OVER (PARTITION BY g ORDER BY d DESC, id) AS premier,
LAST_VALUE(id) OVER (PARTITION BY g ORDER BY d DESC, id
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS dernier
FROM T ORDER BY id;
-- id | g | premier | dernier
-- 1 | a | 2 | 1
-- 2 | a | 2 | 1
-- 3 | a | 2 | 1
-- 4 | b | 6 | 5
-- 5 | b | 6 | 5
-- 6 | b | 6 | 5
-- 7 | b | 6 | 5NTH_VALUE#
NTH_VALUE(expr, n) OVER (...)Valeur de expr dans la n-ième ligne (à partir de 1) du cadre ; NULL si le cadre compte moins de n lignes. n est un entier constant supérieur ou égal à 1 (sinon 1210). Exactement deux arguments (sinon 1582).
SELECT id, g, NTH_VALUE(id, 2) OVER (PARTITION BY g ORDER BY d DESC, id
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM T ORDER BY id;
-- 3 pour les lignes du groupe a (ids 1 à 3), 4 pour celles du groupe b (ids 4 à 7)MEDIAN / PERCENTILE_CONT / PERCENTILE_DISC#
MEDIAN(expr) OVER ([PARTITION BY ...])
PERCENTILE_CONT(fraction) WITHIN GROUP (ORDER BY expr [DESC]) OVER ([PARTITION BY ...])
PERCENTILE_DISC(fraction) WITHIN GROUP (ORDER BY expr [DESC]) OVER ([PARTITION BY ...])Valeur centrale ou percentile de expr sur toute la partition (les valeurs NULL sont écartées ; une partition sans valeur rend NULL). MEDIAN(x) est PERCENTILE_CONT(0.5). PERCENTILE_CONT interpole entre les deux valeurs voisines et rend un DOUBLE (expr numérique) ; PERCENTILE_DISC rend la première valeur dont la position cumulée atteint fraction, de n'importe quel type. fraction est une constante de 0 à 1 (sinon 1210) ; l'ORDER BY du WITHIN GROUP porte sur une seule clé. Ces fonctions n'acceptent ni ORDER BY ni cadre dans leur OVER (erreur 1235) et exigent OVER (sans lui, erreur).
SELECT id, g, MEDIAN(v) OVER (PARTITION BY g) FROM T ORDER BY id;
-- 20.0 pour les lignes du groupe a, 60.0 pour celles du groupe b (le NULL est écarté)
SELECT DISTINCT PERCENTILE_DISC(0.25) WITHIN GROUP (ORDER BY v DESC) OVER (),
PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY v) OVER () FROM T;
-- 60, 22.5Agrégats en fenêtre#
COUNT, SUM, AVG, MIN, MAX, STD, STDDEV, STDDEV_POP et VARIANCE acceptent une clause OVER et se calculent alors sur le cadre de chaque ligne, avec les mêmes règles de types et de NULL qu'en 10.5 (les NULL sont ignorés ; SUM, AVG, MIN, MAX, STD, VARIANCE rendent NULL sur un cadre sans valeur non NULL, COUNT rend 0). COUNT(*) OVER (...) est accepté.
Non pris en charge avec OVER (erreur 1235) : GROUP_CONCAT, JSON_ARRAYAGG, JSON_OBJECTAGG, BIT_AND/BIT_OR/BIT_XOR, ANY_VALUE, STDDEV_SAMP, VAR_POP, VAR_SAMP, DISTINCT dans l'argument, et SUM/AVG/MIN/MAX sur des vecteurs VECTOR(n).
-- somme courante par groupe
SELECT id, g, SUM(v) OVER (PARTITION BY g ORDER BY d, id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM T ORDER BY id;
-- 1, a, 10 / 2, a, 30 / 3, a, 60 / 4, b, 110 / 5, b, NULL / 6, b, 170 / 7, b, 70
-- moyenne mobile sur trois lignes
SELECT id, AVG(d) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) FROM T ORDER BY id;
-- 1.5000, 1.6667, 2.3333, 2.0000, 2.6667, 2.3333, 3.000010.14 Colonnes dynamiques#
Les colonnes dynamiques rangent un jeu de paires clé / valeur dans une colonne BLOB, sous un format binaire compact. Le principe, les types de valeurs (AS INT, AS DOUBLE, AS CHAR, AS DATE...) et un exemple complet sont décrits dans la section « Colonnes dynamiques » du chapitre 6. Types de données. Une clé est un nombre ou un nom ; un blob invalide ou une clé en double rend NULL.
| Fonction | Signature | Retour |
|---|---|---|
| COLUMN_CREATE | COLUMN_CREATE(clé, valeur [AS type] [, clé, valeur ...]) | BLOB |
| COLUMN_ADD | COLUMN_ADD(jeu, clé, valeur [AS type] [, ...]) | BLOB |
| COLUMN_DELETE | COLUMN_DELETE(jeu, clé [, clé ...]) | BLOB |
| COLUMN_GET | COLUMN_GET(jeu, clé AS type) | type demandé |
| COLUMN_EXISTS | COLUMN_EXISTS(jeu, clé) | BIGINT |
| COLUMN_LIST | COLUMN_LIST(jeu) | texte |
| COLUMN_JSON | COLUMN_JSON(jeu) | texte |
| COLUMN_CHECK | COLUMN_CHECK(jeu) | BIGINT |
Les exemples utilisent la table produit (id INT PRIMARY KEY, attrs BLOB).
COLUMN_CREATE#
Construit un jeu à partir de paires clé / valeur (au moins une paire). AS type fixe le type de la valeur stockée ; sans lui, il se déduit de la valeur.
INSERT INTO produit VALUES (1, COLUMN_CREATE('couleur', 'rouge', 'poids', 2.5 AS DOUBLE));
SELECT COLUMN_JSON(COLUMN_CREATE('couleur', 'rouge', 'poids', 2.5 AS DOUBLE)); -- '{"poids":2.5,"couleur":"rouge"}'
SELECT COLUMN_JSON(COLUMN_CREATE(1, 'un', 2, 'deux')); -- '{"1":"un","2":"deux"}'COLUMN_ADD#
Ajoute des colonnes à un jeu, ou remplace celles qui existent déjà (même clé).
UPDATE produit SET attrs = COLUMN_ADD(attrs, 'taille', 42) WHERE id = 1;
SELECT COLUMN_JSON(attrs) FROM produit; -- '{"poids":2.5,"taille":42,"couleur":"rouge"}'COLUMN_DELETE#
Retire les colonnes de clés données ; une clé absente est ignorée.
SELECT COLUMN_JSON(COLUMN_DELETE(attrs, 'taille', 'absente')) FROM produit; -- '{"poids":2.5,"couleur":"rouge"}'COLUMN_GET#
Lit la colonne de clé donnée, convertie vers type (INTEGER, DOUBLE, DECIMAL(p,s), CHAR, DATE, TIME, DATETIME...) ; NULL si la colonne n'existe pas.
SELECT COLUMN_GET(attrs, 'poids' AS DOUBLE), COLUMN_GET(attrs, 'taille' AS CHAR), COLUMN_GET(attrs, 'absente' AS INT)
FROM produit; -- 2.5, '42', NULLCOLUMN_EXISTS#
1 si le jeu contient la clé, 0 sinon.
SELECT COLUMN_EXISTS(attrs, 'couleur'), COLUMN_EXISTS(attrs, 'prix') FROM produit; -- 1, 0COLUMN_LIST#
Liste des clés du jeu, séparées par des virgules et entre apostrophes inverses.
SELECT COLUMN_LIST(attrs) FROM produit; -- '`poids`,`taille`,`couleur`'COLUMN_JSON#
Le jeu en texte JSON compact (voir les exemples ci-dessus).
SELECT COLUMN_JSON(attrs) FROM produit; -- '{"poids":2.5,"taille":42,"couleur":"rouge"}'COLUMN_CHECK#
1 si l'argument est un jeu valide, 0 sinon.
SELECT COLUMN_CHECK(attrs), COLUMN_CHECK('abc') FROM produit; -- 1, 010.15 Fonctions de séquence#
NEXT VALUE FOR s (ou NEXTVAL(s)), PREVIOUS VALUE FOR s (ou LASTVAL(s)) et SETVAL(s, n [, est_appelée]) lisent et font avancer une séquence créée par CREATE SEQUENCE. Leur description et leurs droits figurent au chapitre 7. Langage DDL (section « Séquences ») ; les erreurs 4084 à 4091 sont au chapitre 28.
| Forme | Effet |
|---|---|
NEXT VALUE FOR s, NEXTVAL(s) | Fait avancer la séquence et rend la nouvelle valeur |
PREVIOUS VALUE FOR s, LASTVAL(s) | Dernière valeur servie à la session par s (NULL avant le premier appel) |
SETVAL(s, n [, est_appelée [, tour]]) | Fixe la valeur courante : la prochaine sera n + pas (ou n si est_appelée vaut 0) ; tour : numéro de cycle d'une séquence CYCLE ; rend n |
CREATE SEQUENCE s START WITH 100 INCREMENT BY 10;
SELECT NEXT VALUE FOR s, NEXTVAL(s), PREVIOUS VALUE FOR s, LASTVAL(s); -- 100, 110, 110, 110
SELECT SETVAL(s, 500), NEXTVAL(s); -- 500, 51010.16 Recherche plein texte (MATCH … AGAINST)#
MATCH (col1, col2, …) AGAINST (texte [IN NATURAL LANGUAGE MODE | IN BOOLEAN MODE | IN FUZZY MODE | WITH QUERY EXPANSION]) rend la pertinence (DOUBLE) d'une ligne pour un texte cherché, en s'appuyant sur l'index FULLTEXT dont les colonnes sont exactement col1, col2, … (1191 sinon). La formule du score se choisit par la variable de session miraj_ft_ranking : reference (défaut) ou bm25 (extension MIRAJ, réglée par miraj_ft_bm25_k1 et miraj_ft_bm25_b) ; les poids par colonne se déclarent dans la définition de l'index (FULLTEXT ft (designation WEIGHT 3, notes), chapitre 7). Recherche floue (extension MIRAJ) : mot~1 ou mot~2 en mode booléen, IN FUZZY MODE (distance selon la longueur du mot), bornée par miraj_ft_fuzzy_min_length et miraj_ft_fuzzy_max_expansions ; distance hors de 0 à 2 : 9052. Détail, modes et exemples : chapitre 9, §9.22 ; déclaration de l'index : chapitre 7.
CREATE TABLE articles (id INT PRIMARY KEY, titre VARCHAR(100), corps TEXT, FULLTEXT ft (titre, corps));
INSERT INTO articles VALUES
(1, 'Base de données', 'MIRAJ est une base de données relationnelle'),
(2, 'Recettes', 'Une tarte aux pommes'),
(3, 'Index', 'Un index plein texte accélère la recherche dans la base');
SELECT id, MATCH (titre, corps) AGAINST ('base') AS score
FROM articles WHERE MATCH (titre, corps) AGAINST ('base') ORDER BY score DESC;
-- 1, 0.062016263604164124
-- 3, 0.031008131802082062
SELECT id FROM articles WHERE MATCH (titre, corps) AGAINST ('+base -index' IN BOOLEAN MODE); -- 110.17 Fonctions spatiales#
Une géométrie (GEOMETRY, POINT, LINESTRING, POLYGON, MULTIPOINT, MULTILINESTRING, MULTIPOLYGON, GEOMETRYCOLLECTION) est stockée comme le SRID (4 octets) suivi du WKB, octets au format binaire standard. Tous les calculs sont plans : le SRID est transporté mais n'intervient dans aucun calcul (seuls les MBR* exigent des SRID égaux, erreur 3033). Des octets qui ne forment pas une géométrie rendent NULL.
Les noms sont reconnus avec et sans le préfixe ST_ (ST_AsText / AsText, ST_X / X, ST_Area / Area, ST_Contains / Contains…). Attention : Intersects, Disjoint et Overlaps sans préfixe sont les prédicats sur les boîtes englobantes (MBRIntersects, MBRDisjoint, MBROverlaps), et MBRTouches est le prédicat exact ST_Touches. Un argument qui n'est pas une géométrie (nombre, texte) lève l'erreur 4079.
Conversions#
| Fonction | Description | Exemple | Résultat |
|---|---|---|---|
ST_GeomFromText(wkt [, srid]) | Géométrie lue dans son texte WKT, avec le SRID donné (0 par défaut) ; NULL si le texte est illisible. Synonymes, qui rendent la géométrie lue quel que soit son type : ST_GeometryFromText, ST_PointFromText, ST_LineFromText / ST_LineStringFromText, ST_PolyFromText / ST_PolygonFromText, ST_MPointFromText / ST_MultiPointFromText, ST_MLineFromText / ST_MultiLineStringFromText, ST_MPolyFromText / ST_MultiPolygonFromText, ST_GeomCollFromText / ST_GeometryCollectionFromText (chacun aussi sans ST_) | ST_SRID(ST_GeomFromText('POINT(1 2)', 4326)) | 4326 |
ST_GeomFromWKB(wkb [, srid]) | Géométrie lue dans sa forme binaire WKB ; mêmes synonymes en …FromWKB | ST_AsText(ST_GeomFromWKB(ST_AsBinary(POINT(1, 2)))) | 'POINT(1 2)' |
ST_AsText(g) / ST_AsWKT(g) | Texte WKT | ST_AsText(POINT(1, 2)) | 'POINT(1 2)' |
ST_AsBinary(g) / ST_AsWKB(g) | Forme binaire WKB (sans SRID) | HEX(ST_AsBinary(POINT(1, 2))) | '0101000000000000000000F03F0000000000000040' |
ST_AsGeoJSON(g [, decimales [, options]]) | Document GeoJSON, coordonnées arrondies à decimales | ST_AsGeoJSON(POINT(1.123456, 2), 2) | '{"type": "Point", "coordinates": [1.12, 2]}' |
ST_GeomFromGeoJSON(texte [, options [, srid]]) | Géométrie lue dans un document GeoJSON | ST_AsText(ST_GeomFromGeoJSON('{"type": "Point", "coordinates": [1, 2]}')) | 'POINT(1 2)' |
Constructeurs#
Les constructeurs rendent une géométrie de SRID 0.
| Fonction | Description | Exemple | Résultat |
|---|---|---|---|
POINT(x, y) | Point | ST_AsText(POINT(1, 2)) | 'POINT(1 2)' |
LINESTRING(p1, p2, …) | Ligne brisée à partir de points | ST_AsText(LINESTRING(POINT(0, 0), POINT(1, 1))) | 'LINESTRING(0 0,1 1)' |
POLYGON(l1, l2, …) | Polygone à partir d'anneaux (lignes fermées), le premier extérieur | ST_AsText(POLYGON(LINESTRING(POINT(0, 0), POINT(2, 0), POINT(2, 2), POINT(0, 0)))) | 'POLYGON((0 0,2 0,2 2,0 0))' |
MULTIPOINT(p1, …) | Multipoint | ST_AsText(MULTIPOINT(POINT(0, 0), POINT(1, 1))) | 'MULTIPOINT(0 0,1 1)' |
MULTILINESTRING(l1, …) | Multiligne | ST_AsText(MULTILINESTRING(LINESTRING(POINT(0, 0), POINT(1, 1)))) | 'MULTILINESTRING((0 0,1 1))' |
MULTIPOLYGON(pg1, …) | Multipolygone | ST_AsText(MULTIPOLYGON(POLYGON(LINESTRING(POINT(0, 0), POINT(2, 0), POINT(2, 2), POINT(0, 0))))) | 'MULTIPOLYGON(((0 0,2 0,2 2,0 0)))' |
GEOMETRYCOLLECTION(g1, …) | Collection de géométries quelconques | ST_AsText(GEOMETRYCOLLECTION(POINT(0, 0), LINESTRING(POINT(0, 0), POINT(1, 1)))) | 'GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,1 1))' |
Accesseurs#
| Fonction | Description | Exemple | Résultat |
|---|---|---|---|
ST_X(p), ST_Y(p) | Coordonnées d'un point (DOUBLE) | ST_X(POINT(1, 2)), ST_Y(POINT(1, 2)) | 1.0, 2.0 |
ST_SRID(g) | Identifiant du système de référence | ST_SRID(POINT(1, 2)) | 0 |
ST_GeometryType(g) | Nom du type, en majuscules | ST_GeometryType(POINT(1, 2)) | 'POINT' |
ST_Dimension(g) | 0 point, 1 ligne, 2 surface | ST_Dimension(ST_GeomFromText('POLYGON((0 0,2 0,2 2,0 0))')) | 2 |
ST_IsEmpty(g) | 1 pour une géométrie vide | ST_IsEmpty(ST_GeomFromText('GEOMETRYCOLLECTION EMPTY')) | 0 |
ST_IsSimple(g) | 1 sans auto-intersection | ST_IsSimple(ST_GeomFromText('LINESTRING(0 0,2 2,0 2,2 0)')) | 0 |
ST_IsClosed(l) | 1 si la ligne revient à son point de départ | ST_IsClosed(ST_GeomFromText('LINESTRING(0 0,1 0,1 1,0 0)')) | 1 |
ST_IsRing(l) | 1 pour une ligne fermée et simple | ST_IsRing(ST_GeomFromText('LINESTRING(0 0,1 0,1 1,0 0)')) | 1 |
ST_NumPoints(l) | Nombre de sommets | ST_NumPoints(ST_GeomFromText('LINESTRING(0 0,1 1,2 0)')) | 3 |
ST_PointN(l, n) | n-ième sommet (à partir de 1) | ST_AsText(ST_PointN(ST_GeomFromText('LINESTRING(0 0,1 1,2 0)'), 2)) | 'POINT(1 1)' |
ST_StartPoint(l), ST_EndPoint(l) | Premier et dernier sommet | ST_AsText(ST_EndPoint(ST_GeomFromText('LINESTRING(0 0,1 1,2 0)'))) | 'POINT(2 0)' |
ST_ExteriorRing(pg) | Anneau extérieur d'un polygone | ST_AsText(ST_ExteriorRing(ST_GeomFromText('POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 1))'))) | 'LINESTRING(0 0,4 0,4 4,0 4,0 0)' |
ST_NumInteriorRings(pg) | Nombre de trous | même polygone | 1 |
ST_InteriorRingN(pg, n) | n-ième trou | même polygone, 1 | 'LINESTRING(1 1,2 1,2 2,1 1)' |
ST_NumGeometries(g) | Nombre d'éléments d'une multi-géométrie ou collection | ST_NumGeometries(ST_GeomFromText('MULTIPOINT(0 0,1 1,2 2)')) | 3 |
ST_GeometryN(g, n) | n-ième élément | ST_AsText(ST_GeometryN(ST_GeomFromText('MULTIPOINT(0 0,1 1,2 2)'), 3)) | 'POINT(2 2)' |
ST_Envelope(g) | Boîte englobante | ST_AsText(ST_Envelope(ST_GeomFromText('LINESTRING(0 0,3 2)'))) | 'POLYGON((0 0,3 0,3 2,0 2,0 0))' |
ST_IsValid(g) | 1 si la géométrie est valide (polygone sans auto-intersection…) | ST_IsValid(ST_GeomFromText('POLYGON((0 0,2 2,0 2,2 0,0 0))')) | 0 |
ST_Validate(g) | La géométrie si elle est valide, NULL sinon | ST_AsText(ST_Validate(ST_GeomFromText('POLYGON((0 0,2 0,2 2,0 0))'))) | 'POLYGON((0 0,2 0,2 2,0 0))' |
Prédicats#
Les prédicats rendent 1 ou 0. Les MBR… comparent les boîtes englobantes et exigent des SRID égaux (erreur 3033 sinon) ; les ST_… comparent les géométries exactes.
| Fonction | Vrai si | Exemple | Résultat |
|---|---|---|---|
MBRContains(a, b) | la boîte de a contient celle de b | MBRContains(ST_GeomFromText('POLYGON((0 0,4 0,4 4,0 4,0 0))'), POINT(1, 1)) | 1 |
MBRWithin(a, b) | la boîte de a est dans celle de b | MBRWithin(POINT(1, 1), ST_GeomFromText('POLYGON((0 0,4 0,4 4,0 4,0 0))')) | 1 |
MBRCoveredBy(a, b) | la boîte de a est couverte par celle de b (bord compris) | MBRCoveredBy(POINT(0, 0), ST_GeomFromText('POLYGON((0 0,4 0,4 4,0 4,0 0))')) | 1 |
MBRIntersects(a, b) / Intersects | les boîtes se rencontrent | MBRIntersects(ST_GeomFromText('LINESTRING(0 0,2 2)'), ST_GeomFromText('LINESTRING(0 2,2 0)')) | 1 |
MBRDisjoint(a, b) / Disjoint | les boîtes ne se rencontrent pas | MBRDisjoint(POINT(0, 0), POINT(5, 5)) | 1 |
MBROverlaps(a, b) / Overlaps | les boîtes se chevauchent partiellement | MBROverlaps(ST_GeomFromText('POLYGON((0 0,2 0,2 2,0 2,0 0))'), ST_GeomFromText('POLYGON((1 1,3 1,3 3,1 3,1 1))')) | 1 |
MBREquals(a, b) / MBREqual | les boîtes sont égales | MBREquals(ST_GeomFromText('LINESTRING(0 0,2 2)'), ST_GeomFromText('LINESTRING(0 2,2 0)')) | 1 |
ST_Contains(a, b) / Contains | a contient b | ST_Contains(ST_GeomFromText('POLYGON((0 0,4 0,4 4,0 4,0 0))'), POINT(1, 1)) | 1 |
ST_Within(a, b) / Within | a est dans b | ST_Within(POINT(5, 5), ST_GeomFromText('POLYGON((0 0,4 0,4 4,0 4,0 0))')) | 0 |
ST_Intersects(a, b) | les géométries se rencontrent | ST_Intersects(ST_GeomFromText('LINESTRING(0 0,2 2)'), ST_GeomFromText('LINESTRING(0 3,1 2)')) | 0 (alors que Intersects vaut 1) |
ST_Disjoint(a, b) | les géométries ne se rencontrent pas | ST_Disjoint(POINT(0, 0), POINT(1, 1)) | 1 |
ST_Touches(a, b) / Touches / MBRTouches | les géométries se touchent par leur bord seulement | ST_Touches(ST_GeomFromText('POLYGON((0 0,1 0,1 1,0 1,0 0))'), ST_GeomFromText('POLYGON((1 0,2 0,2 1,1 1,1 0))')) | 1 |
ST_Crosses(a, b) / Crosses | les géométries se croisent | ST_Crosses(ST_GeomFromText('LINESTRING(0 0,2 2)'), ST_GeomFromText('LINESTRING(0 2,2 0)')) | 1 |
ST_Overlaps(a, b) | les géométries se chevauchent partiellement | ST_Overlaps(ST_GeomFromText('POLYGON((0 0,2 0,2 2,0 2,0 0))'), ST_GeomFromText('POLYGON((1 1,3 1,3 3,1 3,1 1))')) | 1 |
ST_Equals(a, b) / Equals | les géométries couvrent le même ensemble de points | ST_Equals(ST_GeomFromText('LINESTRING(0 0,2 2)'), ST_GeomFromText('LINESTRING(2 2,0 0)')) | 1 |
ST_Relate(a, b, motif) | la matrice d'intersection DE-9IM de a et b vérifie motif | ST_Relate(ST_GeomFromText('POLYGON((0 0,4 0,4 4,0 4,0 0))'), POINT(1, 1), 'T*****FF*') | 1 |
Mesures et constructions#
| Fonction | Description | Exemple | Résultat |
|---|---|---|---|
ST_Area(g) / Area | Aire (plane) | ST_Area(ST_GeomFromText('POLYGON((0 0,4 0,4 4,0 4,0 0))')) | 16.0 |
ST_Length(g) / GLength | Longueur d'une ligne | ST_Length(ST_GeomFromText('LINESTRING(0 0,3 4)')) | 5.0 |
ST_Distance(a, b) | Distance plane minimale | ST_Distance(POINT(0, 0), POINT(3, 4)) | 5.0 |
ST_Distance_Sphere(a, b [, rayon]) | Distance sur la sphère entre deux points (longitude, latitude en degrés), rayon terrestre de 6 370 986 m par défaut | ROUND(ST_Distance_Sphere(POINT(2.3522, 48.8566), POINT(-0.1276, 51.5072))) | 343529.0 (Paris–Londres, en mètres) |
ST_Centroid(g) / Centroid | Centre de gravité | ST_AsText(ST_Centroid(ST_GeomFromText('POLYGON((0 0,4 0,4 4,0 4,0 0))'))) | 'POINT(2 2)' |
ST_PointOnSurface(g) | Un point situé sur la géométrie | même polygone | 'POINT(2 2)' |
ST_Boundary(g) / Boundary | Bord (extrémités d'une ligne, anneaux d'un polygone) | ST_AsText(ST_Boundary(ST_GeomFromText('LINESTRING(0 0,1 1,2 0)'))) | 'MULTIPOINT(0 0,2 0)' |
ST_ConvexHull(g) / ConvexHull | Enveloppe convexe | ST_AsText(ST_ConvexHull(ST_GeomFromText('MULTIPOINT(0 0,2 0,1 1,1 3)'))) | 'POLYGON((0 0,1 3,2 0,0 0))' |
ST_Simplify(g, tolerance) / Simplify | Géométrie simplifiée (sommets à moins de tolerance du tracé retirés) | ST_AsText(ST_Simplify(ST_GeomFromText('LINESTRING(0 0,1 0.1,2 0,3 2)'), 0.5)) | 'LINESTRING(0 0,2 0,3 2)' |
ST_Union / ST_Intersection / ST_Difference / ST_SymDifference#
ST_Union(a, b) ST_Intersection(a, b) ST_Difference(a, b) ST_SymDifference(a, b)Réunion, intersection, différence (a privé de b) et différence symétrique de deux géométries de tous types (points, lignes, polygones, multi-géométries, collections ; un multipolygone est l'union de ses polygones). Le résultat a une forme normalisée : anneaux en sens horaire, trous compris, départ au sommet le plus bas puis le plus à gauche ; polygones, lignes et points rangés par leur sommet le plus bas ; un seul élément → lui-même, éléments du même type → multi-géométrie, mélange → GEOMETRYCOLLECTION, rien → GEOMETRYCOLLECTION EMPTY. Une différence ignore ce qui est de dimension inférieure (ST_Difference(ligne, point) rend la ligne). Le SRID du résultat est 0 ; un argument NULL, illisible ou vide (GEOMETRYCOLLECTION EMPTY) rend NULL ; un nombre ou un texte → 4079.
SELECT ST_AsText(ST_Union(ST_GeomFromText('POLYGON((0 0,4 0,4 4,0 4,0 0))'),
ST_GeomFromText('POLYGON((2 2,6 2,6 6,2 6,2 2))')));
-- POLYGON((0 0,0 4,2 4,2 6,6 6,6 2,4 2,4 0,0 0))
SELECT ST_AsText(ST_Difference(ST_GeomFromText('LINESTRING(-1 2,5 2)'),
ST_GeomFromText('POLYGON((0 0,4 0,4 4,0 4,0 0))')));
-- MULTILINESTRING((-1 2,0 2),(4 2,5 2))ST_Buffer / Buffer#
ST_Buffer(g, distance)Zone des points à moins de distance de g, construite ainsi : un cercle compte 126 sommets (pas de π/64 ; 32 segments par quart de cercle, aux deux points de raccord près), les lignes ont des bouts arrondis et des raccords arrondis du côté extérieur des virages, les coins d'un polygone sont arrondis. Une distance négative rétrécit les polygones et ne laisse rien d'un point ou d'une ligne (GEOMETRYCOLLECTION EMPTY). Une distance nulle (en valeur absolue inférieure à 1e-11) rend la géométrie telle quelle, SRID compris ; sinon le SRID du résultat est 0. Deux arguments exactement (1582 sinon).
SELECT ST_NumPoints(ST_ExteriorRing(ST_Buffer(POINT(0, 0), 1))); -- 127 (anneau fermé)
SELECT ST_AsText(ST_Buffer(ST_GeomFromText('POLYGON((0 0,2 0,2 2,0 2,0 0))'), -0.5));
-- POLYGON((0.5 0.5,0.5 1.5,1.5 1.5,1.5 0.5,0.5 0.5))Geohash#
ST_GeoHash(point, longueur) ou ST_GeoHash(longitude, latitude, longueur) rend le code geohash (longueur entière de 1 à 100, sinon 3048 ; longitude dans [-180, 180], latitude dans [-90, 90], sinon 3048 ; géométrie qui n'est pas un point → 3037). Le code s'arrête plus tôt quand la cellule a exactement le point pour centre. ST_LatFromGeoHash(code) et ST_LongFromGeoHash(code) rendent le centre de la cellule arrondi au plus petit nombre de décimales qui reste dans la cellule ; ST_PointFromGeoHash(code, srid) rend le point. Casse libre ; caractère hors alphabet ou code vide → 1411.
SELECT ST_GeoHash(-122.4194, 37.7749, 12), ST_LatFromGeoHash('ezs42'); -- '9q8yyk8ytpxr', 42.6ST_SRID, ST_X et ST_Y n'acceptent qu'un argument : la forme à deux arguments rend 1582.
ST_Collect#
ST_Collect([DISTINCT] geometrie)Fonction d'agrégation : rassemble les géométries non NULL du groupe en une seule, MULTIPOINT, MULTILINESTRING ou MULTIPOLYGON si elles sont toutes du même type, GEOMETRYCOLLECTION sinon. DISTINCT écarte les doublons. Elle s'emploie aussi en fonction de fenêtrage (OVER).
SELECT ST_AsText(ST_Collect(POINT(x, x))) FROM mesures; -- 'MULTIPOINT(2 2,4 4,4 4,6 6)'
SELECT ST_AsText(ST_Collect(DISTINCT POINT(x, x))) FROM mesures; -- 'MULTIPOINT(2 2,4 4,6 6)'Index spatial#
Un index SPATIAL (chapitre 7) sert les conjoncts MBRContains, MBRWithin, MBRCoveredBy, MBRIntersects / Intersects, MBROverlaps / Overlaps, MBREqual(s), MBRTouches, ST_Contains, ST_Within, ST_Intersects, ST_Equals, ST_Touches, ST_Crosses, ST_Overlaps (et Contains, Within, Touches, Crosses, Equals) entre la colonne indexée et une constante (littéral, variable @q, paramètre, expression constante comme ST_Buffer(POINT(1, 1), 2)), dans les deux ordres, en SELECT, UPDATE et DELETE : seules les lignes dont la boîte englobante convient sont lues, le prédicat exact restant au filtre ; plusieurs conjoncts servis se combinent. EXPLAIN affiche type = range, key = l'index, key_len = 34, rows = lignes candidates. Jamais servis : NOT, OR, = 1, ST_Disjoint, MBRDisjoint, ST_Distance(…) < r, deux colonnes, une jointure, ORDER BY ST_Distance(…) LIMIT k (lecture complète puis tri). Les écritures non validées d'une transaction sont vues par elle, jamais par les autres sessions.
10.18 Fonctions XML#
Les deux fonctions XML lisent un fragment XML (un texte, qui peut avoir plusieurs éléments racines) et une expression XPath 1.0 : chemins absolus et relatifs, //, axes child, attribute (@nom), self, parent, descendant, descendant-or-self, ancestor, ancestor-or-self, following-sibling, preceding-sibling, tests nom, *, text(), node(), prédicats ([2], [@n="2"], [last()]), opérateurs or and = != < <= > >= + - * div mod | et les fonctions count, last, position, string, concat, contains, starts-with, substring, substring-before, substring-after, string-length, normalize-space, translate, not, boolean, number, sum, floor, ceiling, round, name, local-name, true, false. Un XML mal formé rend NULL avec l'avertissement 1525 ; une expression XPath invalide lève l'erreur 1105 (XPATH syntax error).
| Fonction | Signature |
|---|---|
| EXTRACTVALUE | EXTRACTVALUE(xml, xpath) |
| UPDATEXML | UPDATEXML(xml, xpath, nouveau_xml) |
EXTRACTVALUE#
EXTRACTVALUE(xml, xpath)Texte des nœuds désignés par xpath : le texte direct de chaque élément trouvé (ou la valeur de l'attribut), les valeurs de plusieurs nœuds séparées par une espace ; chaîne vide si rien n'est trouvé. Une expression qui calcule une valeur (count(…), sum(…), name(…)) rend cette valeur en texte.
Retour : texte.
SELECT EXTRACTVALUE('<a><b>x</b><b>y</b></a>', '/a/b'); -- 'x y'
SELECT EXTRACTVALUE('<a><b>x</b><b>y</b></a>', '/a/b[2]'); -- 'y'
SELECT EXTRACTVALUE('<a><b>x</b><b>y</b></a>', '/a/c'); -- '' (rien trouvé)
SELECT EXTRACTVALUE('<livre id="7"><titre>SQL</titre></livre>', '/livre/@id'); -- '7'
SELECT EXTRACTVALUE('<a><b n="1">x</b><b n="2">y</b></a>', '/a/b[@n="2"]'); -- 'y'
SELECT EXTRACTVALUE('<a><b/><b/></a>', 'count(/a/b)'); -- '2'
SELECT EXTRACTVALUE('<a><b>1</b><b>2</b></a>', 'sum(//b)'); -- '3'
SELECT EXTRACTVALUE('<a>', '/a'); -- NULL (avertissement 1525)UPDATEXML#
UPDATEXML(xml, xpath, nouveau_xml)Remplace par nouveau_xml l'élément désigné par xpath, s'il en désigne exactement un ; sinon (aucun ou plusieurs éléments), xml est rendu inchangé.
Retour : texte.
SELECT UPDATEXML('<a><b>x</b><c>y</c></a>', '/a/b', '<b>z</b>'); -- '<a><b>z</b><c>y</c></a>'
SELECT UPDATEXML('<a><b>x</b><b>y</b></a>', '/a/b', '<c/>'); -- '<a><b>x</b><b>y</b></a>' (deux éléments désignés)
SELECT UPDATEXML('<a><b>x</b></a>', '/a/z', '<c/>'); -- '<a><b>x</b></a>' (aucun)10.19 Opérateurs#
Sauf mention contraire, un opérateur dont un opérande vaut NULL rend NULL. Les comparaisons et les opérateurs logiques rendent 1 (vrai), 0 (faux) ou NULL (inconnu) ; TRUE et FALSE valent 1 et 0.
Opérateurs arithmétiques#
| Opérateur | Effet | Exemple | Résultat |
|---|---|---|---|
+, -, * | Addition, soustraction, multiplication ; un texte est lu par son préfixe numérique | 2 * 3.5, '3abc' + 1 | 7.0, 4.0 |
/ | Division, résultat décimal (4 décimales de plus que le dividende) ; NULL pour une division par zéro | 7 / 2, 1 / 3, 10 / 0 | 3.5000, 0.3333, NULL |
DIV | Division entière, tronquée vers zéro ; NULL par zéro | 7 DIV 2, -7 DIV 2 | 3, -3 |
%, MOD | Reste de la division, du signe du dividende ; NULL par zéro | 7 % 3, -7 % 3, 7.5 % 2 | 1, -1, 1.5 |
- (unaire), + (unaire) | Opposé, identité | - -3 | 3 |
Une division (/, DIV, %, MOD) par zéro rend NULL ; quand le sql_mode contient ERROR_FOR_DIVISION_BY_ZERO, elle ajoute l'avertissement 1365 (erreur 1365 dans une écriture en mode strict, voir le chapitre 28). L'avertissement est compté comme par la référence : une fois par ligne pour une expression de la liste du SELECT, y compris une sous-requête sans table réduite à son expression ((SELECT 1/0)), mais une seule fois pour une condition constante du WHERE (WHERE 1/0 IS NULL, deux fois pour un DELETE). Une contrainte CHECK dont l'évaluation échoue ainsi rend l'erreur 1365, suivie de 4025 dans SHOW WARNINGS.
Un résultat entier hors de la plage d'un BIGINT lève l'erreur 1690 (SELECT 9223372036854775807 + 1). Une date plus ou moins un intervalle (expr + INTERVAL n unité, INTERVAL n unité + expr, expr - INTERVAL n unité) équivaut à DATE_ADD / DATE_SUB : DATE '2026-09-13' + INTERVAL 1 DAY vaut '2026-09-14'. Entre deux vecteurs, +, - et * opèrent élément par élément (10.11).
Opérateurs de comparaison#
| Opérateur | Vrai si | Exemple | Résultat |
|---|---|---|---|
= | égalité (textes comparés selon l'interclassement, espaces finales ignorées) | 'abc' = 'ABC ' | 1 |
<>, != | différence | 1 != 2 | 1 |
<, <=, >, >= | ordre ; deux textes se comparent comme des textes, un nombre et un texte comme des nombres | '10' < '9', 10 < '9' | 1, 0 |
<=> | égalité qui traite NULL comme une valeur (ne rend jamais NULL) ; entre deux vecteurs, distance cosinus | 1 <=> NULL, NULL <=> NULL | 0, 1 |
IS [NOT] DISTINCT FROM | NOT (a <=> b) / a <=> b | NULL IS DISTINCT FROM 1 | 1 |
IS [NOT] NULL | la valeur est (n'est pas) NULL | NULL IS NULL, 1 IS NOT NULL | 1, 1 |
IS [NOT] TRUE, IS [NOT] FALSE, IS [NOT] UNKNOWN | test d'une valeur logique (jamais NULL) | 2 IS TRUE, 0 IS FALSE, NULL IS UNKNOWN | 1, 1, 1 |
expr [NOT] BETWEEN a AND b | a <= expr <= b | 5 BETWEEN 1 AND 10 | 1 |
expr [NOT] IN (v1, v2, …) | expr égale l'une des valeurs ; NOT IN rend NULL si la liste contient NULL sans correspondance | 3 IN (1, 2, 3), 4 NOT IN (1, 2, NULL) | 1, NULL |
expr [NOT] IN (sous-requête), expr op ANY / SOME / ALL (sous-requête), EXISTS (sous-requête) | comparaison à des lignes d'une sous-requête (chapitre 9, §9.16) | 3 > ANY (SELECT 1 UNION SELECT 5), 3 > ALL (SELECT 1 UNION SELECT 5) | 1, 0 |
(a, b) op (c, d), ROW(a, b) op ROW(c, d) | comparaison de lignes, élément par élément | (1, 2) < (1, 3), (1, NULL) = (1, 2) | 1, NULL |
Opérateurs logiques#
| Opérateur | Effet | Exemple | Résultat |
|---|---|---|---|
NOT, ! | négation (NOT NULL vaut NULL) | NOT 0, !1 | 1, 0 |
AND, && | et : 0 dès qu'un opérande est faux, même si l'autre est NULL | 1 && 0, 0 AND NULL | 0, 0 |
OR, || | ou : 1 dès qu'un opérande est vrai, même si l'autre est NULL | 1 || 0, 'a' || 'b' | 1, 0 |
XOR | ou exclusif | 1 XOR 1, 1 XOR 0 | 0, 1 |
Par défaut, || est le OU logique en langage MIRAJ ; pour concaténer, utiliser CONCAT. Quand le sql_mode de la session contient PIPES_AS_CONCAT (ou le mode composé ANSI, qui l'inclut), || devient la concaténation, équivalente à CONCAT (NULL propage), avec une priorité plus forte que ^ et plus faible que les opérateurs unaires. Le changement vaut dès l'instruction qui suit le SET sql_mode, y compris dans le même script et pour les instructions préparées ensuite :
SELECT 1 || 0; -- 1 (OU logique)
SET sql_mode = 'PIPES_AS_CONCAT';
SELECT 'a' || 'b' || 'c'; -- 'abc'
SELECT 1 + 2 || 3; -- 24 : 2 || 3 vaut '23', puis 1 + '23'
SELECT 'x' || NULL; -- NULL
SET sql_mode = DEFAULT;Opérateurs bit à bit#
Les opérandes sont lus comme des entiers de 64 bits ; le résultat est un entier sans signe.
| Opérateur | Effet | Exemple | Résultat |
|---|---|---|---|
& | et bit à bit | 5 & 3 | 1 |
| | ou bit à bit | 5 | 3 | 7 |
^ | ou exclusif bit à bit | 5 ^ 3 | 6 |
~ | complément | ~5 | 18446744073709551610 |
<<, >> | décalage à gauche, à droite | 1 << 4, 256 >> 2, -1 >> 60 | 16, 64, 15 |
Opérateurs de motifs#
| Opérateur | Vrai si | Exemple | Résultat |
|---|---|---|---|
expr [NOT] LIKE motif [ESCAPE c] | expr correspond à motif : % toute suite de caractères, _ un caractère, \ (ou c) échappe le caractère suivant ; comparaison selon l'interclassement | 'abc' LIKE 'a%', 'a%c' LIKE 'a|%c' ESCAPE '|', 'Ab' LIKE 'ab' | 1, 1, 1 |
expr [NOT] REGEXP motif, expr [NOT] RLIKE motif | motif (expression régulière, 10.6) correspond quelque part dans expr | 'abc' REGEXP '^a', 'abc' NOT REGEXP 'z' | 1, 1 |
a SOUNDS LIKE b | SOUNDEX(a) = SOUNDEX(b) | 'Robert' SOUNDS LIKE 'Rupert' | 1 |
valeur MEMBER OF (document) | valeur est un élément du tableau JSON (10.10) | 2 MEMBER OF ('[1, 2]') | 1 |
Autres opérateurs#
| Opérateur | Effet | Exemple | Résultat |
|---|---|---|---|
doc -> 'chemin', doc ->> 'chemin' | Extraction JSON (10.10) | '{"a": 1}' -> '$.a' | '1' |
<->, <#>, <+> | Distance euclidienne, produit scalaire négé, distance L1 entre vecteurs (10.11) | STRING_TO_VECTOR('[0, 0]') <-> '[3, 4]' | 5.0 |
expr COLLATE interclassement | Impose l'interclassement d'un texte (chapitre 13) | 'Ab' COLLATE utf8mb4_bin = 'ab' | 0 |
BINARY expr | Lit expr comme une chaîne binaire (comparaison octet par octet) | BINARY 'a' = 'A' | 0 |
@nom := expr | Affecte la variable utilisateur @nom et vaut la valeur affectée | @x := 5, @x + 1 | 5, 6 |
CASE … WHEN … THEN … [ELSE …] END | Expression conditionnelle (chapitre 9) | CASE 2 WHEN 1 THEN 'un' WHEN 2 THEN 'deux' ELSE 'autre' END | 'deux' |
Conversion de type (CAST et CONVERT)#
CAST(expr AS type)
CONVERT(expr, type)
CONVERT(expr USING jeu_de_caracteres)type vaut SIGNED [INTEGER], UNSIGNED [INTEGER], DECIMAL[(p[, s])], DOUBLE, FLOAT, REAL, CHAR[(n)] (avec CHARACTER SET facultatif), NCHAR[(n)], BINARY[(n)], DATE, TIME[(fsp)], DATETIME[(fsp)], YEAR, JSON ou VECTOR(n). Les règles de conversion de chaque type sont au chapitre 6. Types de données ; la forme USING est décrite en CONVERT (jeu de caractères).
SELECT CAST('12.5' AS DECIMAL(5,2)), CAST(3.7 AS SIGNED), CONVERT('42', UNSIGNED); -- 12.50, 4, 42
SELECT CAST('2026-09-13' AS DATE), CAST('10:30' AS TIME), CAST('2026-09-13 10:00' AS DATETIME(3));
-- '2026-09-13', '10:30:00', '2026-09-13 10:00:00.000'
SELECT CAST(65 AS CHAR), CAST(5 AS DOUBLE), CAST('{"a":1}' AS JSON); -- '65', 5.0, '{"a":1}'Priorité des opérateurs#
De la plus forte à la plus faible (les opérateurs d'une même ligne se lisent de gauche à droite) ; des parenthèses imposent un autre ordre :
| Priorité | Opérateurs |
|---|---|
| 1 | - et + unaires, ~, !, BINARY, COLLATE |
| 2 | ^ |
| 3 | *, /, DIV, %, MOD |
| 4 | +, - |
| 5 | <<, >>, <->, <#>, <+> |
| 6 | & |
| 7 | | |
| 8 | =, <=>, <>, !=, <, <=, >, >=, IS, LIKE, REGEXP, RLIKE, IN, BETWEEN, SOUNDS LIKE, MEMBER OF |
| 9 | NOT |
| 10 | AND, && |
| 11 | XOR |
| 12 | OR, || |
| 13 | := |
Sous PIPES_AS_CONCAT (ou ANSI), || quitte la ligne 12 et se place entre les lignes 1 et 2 : plus liant que ^, moins que les opérateurs unaires.
SELECT 1 + 2 * 3, 2 + 3 << 1, 5 & 3 | 8, 1 OR 0 AND 0, NOT 1 = 2; -- 7, 10, 9, 1, 1