Charger un fichier
  1. base64hub
  2. Base64 dans le code
  3. SQL
Code

Base64 en SQL

Toutes les grandes bases de données savent faire du Base64, chacune avec ses propres noms de fonctions et sa propre façon d’échouer. Les résultats ci-dessous proviennent de MySQL 8.4, PostgreSQL 17 et SQL Server 2022 et 2025.

MySQL et MariaDB : TO_BASE64 et FROM_BASE64

SELECT TO_BASE64('héllo wörld');
-- aMOpbGxvIHfDtnJsZA==   (connection charset utf8mb4)

SELECT CONVERT(FROM_BASE64('aMOpbGxvIHfDtnJsZA==') USING utf8mb4);
-- héllo wörld

TO_BASE64 encode les octets de la chaîne dans son jeu de caractères. Avec utf8mb4, vous obtenez de l’UTF-8 ; une colonne latin1 donne des octets Latin-1, si bien que TO_BASE64(CONVERT('héllo' USING latin1)) renvoie aOlsbG8= au lieu de aMOpbGxv. FROM_BASE64 renvoie une chaîne binaire ; CONVERT(... USING utf8mb4) la retransforme en texte.

TO_BASE64 coupe les lignes à 76 caractères, comme MIME :

SELECT LENGTH(TO_BASE64(REPEAT('x', 60)));            -- 81 (80 chars + 1 newline)
SELECT REPLACE(TO_BASE64(REPEAT('x', 60)), '\n', ''); -- single line, 80 chars

Une entrée invalide ne provoque pas d’erreur. FROM_BASE64 renvoie NULL :

EntréeRésultat
aGk=hi
aGkNULL (sans remplissage)
aGk=!!NULL
PDw_Pz8-Pg==NULL (URL-safe)
aNULL
aGl=hi (bits de remplissage non nuls acceptés)
'aGVs\nbG8K', 'aGVs bG8K'hello\n (espaces ignorés)

Conversion URL-safe avec les fonctions de chaîne :

SELECT TRIM(TRAILING '=' FROM REPLACE(REPLACE(TO_BASE64('<<???>>'), '+', '-'), '/', '_'));
-- PDw_Pz8-Pg

SELECT FROM_BASE64(CONCAT(
  REPLACE(REPLACE('PDw_Pz8-Pg', '-', '+'), '_', '/'),
  REPEAT('=', (4 - LENGTH('PDw_Pz8-Pg') % 4) % 4)));
-- <<???>>

Pour des valeurs plus longues, enveloppez aussi l’encodeur dans REPLACE(..., '\n', ''). Les deux fonctions existent depuis MySQL 5.6 et dans MariaDB.

PostgreSQL : encode et decode

PostgreSQL travaille sur bytea. Convertissez le texte avec convert_to et revenez en arrière avec convert_from :

SELECT encode(convert_to('héllo wörld', 'UTF8'), 'base64');
-- aMOpbGxvIHfDtnJsZA==

SELECT convert_from(decode('aMOpbGxvIHfDtnJsZA==', 'base64'), 'UTF8');
-- héllo wörld

Comme MySQL, encode(..., 'base64') coupe à 76 caractères ; psql affiche le saut de ligne sous la forme d’un + en fin de ligne. Supprimez-le avec replace(encode(x, 'base64'), E'\n', '').

Contrairement à MySQL, une entrée invalide déclenche une erreur :

decode('aGk', 'base64')
ERROR:  invalid base64 end sequence
HINT:  Input data is missing padding, is truncated, or is otherwise corrupted.

decode('PDw_Pz8-Pg==', 'base64')
ERROR:  invalid symbol "_" found while decoding base64 sequence

aGk=!! échoue avec invalid symbol "!" et a avec invalid base64 end sequence. Les espaces, sauts de ligne compris, sont ignorés, et aGl= est accepté.

PostgreSQL 17 et 18 n’ont pas de format base64url (unrecognized encoding: "base64url") : convertissez donc avec translate.

SELECT translate(rtrim(encode('<<???>>'::bytea, 'base64'), '='), '+/', '-_');
-- PDw_Pz8-Pg

SELECT convert_from(decode(
  rpad(translate('PDw_Pz8-Pg', '-_', '+/'), (length('PDw_Pz8-Pg') + 3) / 4 * 4, '='),
  'base64'), 'UTF8');
-- <<???>>

Pour valider sans faire échouer une transaction, enveloppez decode dans une fonction PL/pgSQL avec un bloc EXCEPTION WHEN others qui renvoie NULL.

SQL Server : l’astuce XML base64Binary

Avant SQL Server 2025, il n’y a pas de fonction Base64. Le type XML convertit entre varbinary et xs:base64Binary, qui n’est autre que du Base64 :

-- encode
DECLARE @bin varbinary(max) = CAST('hi' AS varbinary(max));
SELECT CAST('' AS xml).value('xs:base64Binary(sql:variable("@bin"))', 'varchar(max)');
-- aGk=

-- decode
DECLARE @b64 varchar(max) = 'aGk=';
SELECT CAST('' AS xml).value('xs:base64Binary(sql:variable("@b64"))', 'varbinary(max)');
-- 0x6869

FOR XML ... BINARY BASE64 et FOR JSON émettent aussi les colonnes varbinary en Base64 : SELECT CAST('hi' AS varbinary(max)) AS bin FOR JSON PATH renvoie [{"bin":"aGk="}]. La conversion XML ne coupe pas les lignes : 60 octets ont donné une seule chaîne de 80 caractères.

Les méthodes XML exigent QUOTED_IDENTIFIER ON. Par défaut, sqlcmd le désactive, ce qui donne Msg 1934: SELECT failed because the following SET options have incorrect settings: 'QUOTED_IDENTIFIER'. Passez -I ou exécutez SET QUOTED_IDENTIFIER ON.

Encodage du texte dans SQL Server

nvarchar est en UTF-16LE : CAST(N'héllo wörld' AS varbinary(max)) s’encode donc en aADpAGwAbABvACAAdwD2AHIAbABkAA==, que les autres systèmes décodent avec des blancs entre les lettres. Pour de l’UTF-8 (SQL Server 2019+), passez d’abord par un classement UTF-8 :

DECLARE @bin varbinary(max) = CAST(CAST(N'héllo wörld'
    COLLATE Latin1_General_100_CI_AS_SC_UTF8 AS varchar(max)) AS varbinary(max));
-- encodes to aMOpbGxvIHfDtnJsZA==

Pour redécoder de l’UTF-8, il faut une cible UTF-8. Un simple CAST(@raw AS varchar(max)) dans une base qui utilise le classement par défaut SQL_Latin1_General_CP1_CI_AS affiche héllo wörld. Insérer les octets dans une colonne déclarée varchar(max) COLLATE Latin1_General_100_CI_AS_SC_UTF8 donne héllo wörld. Pour des données UTF-16, CAST(@raw AS nvarchar(max)) suffit.

Erreurs

Avec un littéral de chaîne, un Base64 invalide échoue dès la compilation : Msg 9319: XQuery [value()]: Static simple type validation: Invalid simple type value 'aGk'. La même entrée passée via sql:variable renvoie NULL à la place. Le remplissage manquant, les caractères URL-safe (PDw_Pz8-Pg==) et les bits de remplissage non nuls (aGl=) ont tous été rejetés ; un saut de ligne à l’intérieur de la chaîne a été accepté.

SQL Server 2025 : BASE64_ENCODE et BASE64_DECODE

SQL Server 2025 (17.x) et Azure SQL ajoutent de vraies fonctions, avec une option URL-safe :

SELECT BASE64_ENCODE(0x3C3C3F3F3F3E3E);      -- PDw/Pz8+Pg==
SELECT BASE64_ENCODE(0x3C3C3F3F3F3E3E, 1);   -- PDw_Pz8-Pg   (url_safe, no padding)
SELECT BASE64_DECODE('PDw_Pz8-Pg');          -- 0x3C3C3F3F3F3E3E

BASE64_ENCODE n’accepte que du varbinary ; lui passer du varchar échoue avec Msg 8116: Argument data type varchar(max) is invalid for argument 1 of base64_encode function. BASE64_DECODE accepte les deux alphabets, avec ou sans remplissage, ainsi que aGl=. Une entrée invalide comme aGk=!! ou a déclenche Msg 9803: Invalid data for type "Base64Decode".

Pièges communs à toutes les bases

  • Le jeu de caractères de l’entrée. Le même texte donne un Base64 différent dans une colonne latin1, une colonne utf8mb4 et une colonne nvarchar. Fixez-vous sur des octets UTF-8 et convertissez explicitement.
  • Les sauts de ligne cachés. MySQL et PostgreSQL coupent à 76 caractères. Les consommateurs de JSON et les en-têtes HTTP cassent sur le \n intégré.
  • Les NULL silencieux. MySQL et l’astuce XML de SQL Server renvoient NULL pour une entrée invalide, qu’un JOIN ou un WHERE écarte sans bruit.
  • Les grosses valeurs. Encoder un BLOB dans une requête fait transiter 33 % de données en plus sur le réseau. Pour vérifier une valeur stockée à la main, sélectionnez son Base64 et ouvrez-le avec Base64 en fichier ou Base64 en hex.

FAQ

Pourquoi FROM_BASE64 de MySQL renvoie-t-il NULL ?

MySQL renvoie NULL au lieu d’une erreur pour une entrée invalide : remplissage manquant, - ou _ URL-safe, caractères parasites. Vérifiez l’entrée avec le validateur Base64, et corrigez les chaînes URL-safe avec REPLACE avant de décoder.

Pourquoi la sortie de TO_BASE64 dans MySQL contient-elle des sauts de ligne ?

TO_BASE64 suit la convention MIME et insère un saut de ligne tous les 76 caractères. Enveloppez-la dans REPLACE(TO_BASE64(x), '\n', '') pour une sortie sur une seule ligne.

SQL Server a-t-il une fonction Base64 ?

SQL Server 2025 et Azure SQL proposent BASE64_ENCODE et BASE64_DECODE. Les versions plus anciennes n’ont pas de fonction, mais la conversion XML xs:base64Binary fait l’affaire.

Faut-il stocker des fichiers en Base64 dans la base de données ?

En général, non. Une colonne binaire (BLOB, bytea, varbinary) stocke les mêmes données en occupant environ 25 % de moins et évite la conversion. N’encodez qu’au moment d’envoyer les données à un système qui a besoin de texte. Voir le surcoût de taille de Base64.

Continuer la lecture