MySQL und MariaDB: TO_BASE64 und 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 kodiert die Bytes des Strings in dessen Zeichensatz. Mit utf8mb4 erhalten Sie UTF-8; eine latin1-Spalte liefert Latin-1-Bytes, TO_BASE64(CONVERT('héllo' USING latin1)) ergibt also aOlsbG8= statt aMOpbGxv. FROM_BASE64 liefert einen Binärstring; CONVERT(... USING utf8mb4) macht wieder Text daraus.
TO_BASE64 bricht Zeilen wie MIME nach 76 Zeichen um:
SELECT LENGTH(TO_BASE64(REPEAT('x', 60))); -- 81 (80 chars + 1 newline)
SELECT REPLACE(TO_BASE64(REPEAT('x', 60)), '\n', ''); -- single line, 80 chars
Ungültige Eingaben lösen keinen Fehler aus. FROM_BASE64 liefert NULL:
| Eingabe | Ergebnis |
|---|---|
aGk= | hi |
aGk | NULL (ohne Padding) |
aGk=!! | NULL |
PDw_Pz8-Pg== | NULL (URL-sicher) |
a | NULL |
aGl= | hi (Padding-Bits ungleich null akzeptiert) |
'aGVs\nbG8K', 'aGVs bG8K' | hello\n (Leerraum ignoriert) |
URL-sichere Umwandlung mit String-Funktionen:
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)));
-- <<???>>
Bei längeren Werten umhüllen Sie den Encoder zusätzlich mit REPLACE(..., '\n', ''). Beide Funktionen gibt es seit MySQL 5.6 und auch in MariaDB.
PostgreSQL: encode und decode
PostgreSQL arbeitet mit bytea. Wandeln Sie Text mit convert_to um und mit convert_from zurück:
SELECT encode(convert_to('héllo wörld', 'UTF8'), 'base64');
-- aMOpbGxvIHfDtnJsZA==
SELECT convert_from(decode('aMOpbGxvIHfDtnJsZA==', 'base64'), 'UTF8');
-- héllo wörld
Wie MySQL bricht encode(..., 'base64') nach 76 Zeichen um; psql zeigt den Zeilenumbruch als + am Zeilenende. Entfernen Sie ihn mit replace(encode(x, 'base64'), E'\n', '').
Anders als MySQL löst eine ungültige Eingabe einen Fehler aus:
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=!! scheitert mit invalid symbol "!" und a mit invalid base64 end sequence. Leerraum einschließlich Zeilenumbrüchen und Leerzeichen wird ignoriert, und aGl= wird akzeptiert.
PostgreSQL 17 und 18 haben kein Format base64url (unrecognized encoding: "base64url"), wandeln Sie also mit translate um:
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');
-- <<???>>
Um zu prüfen, ohne eine Transaktion abzubrechen, umhüllen Sie decode mit einer PL/pgSQL-Funktion, deren Block EXCEPTION WHEN others den Wert NULL zurückgibt.
SQL Server: der Trick mit XML base64Binary
Vor SQL Server 2025 gibt es keine Base64-Funktion. Der XML-Typ wandelt zwischen varbinary und xs:base64Binary um, und das ist 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
Auch FOR XML ... BINARY BASE64 und FOR JSON geben varbinary-Spalten als Base64 aus: SELECT CAST('hi' AS varbinary(max)) AS bin FOR JSON PATH liefert [{"bin":"aGk="}]. Die XML-Umwandlung bricht keine Zeilen um: 60 Bytes ergaben einen einzigen String mit 80 Zeichen.
Die XML-Methoden brauchen QUOTED_IDENTIFIER ON. sqlcmd hat standardmäßig off, was zu Msg 1934: SELECT failed because the following SET options have incorrect settings: 'QUOTED_IDENTIFIER' führt. Übergeben Sie -I oder führen Sie SET QUOTED_IDENTIFIER ON aus.
Textkodierung in SQL Server
nvarchar ist UTF-16LE, CAST(N'héllo wörld' AS varbinary(max)) wird also zu aADpAGwAbABvACAAdwD2AHIAbABkAA== kodiert, was andere Systeme mit Lücken zwischen den Buchstaben dekodieren. Für UTF-8 (SQL Server 2019+) gehen Sie zuerst über eine UTF-8-Sortierung:
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==
Um UTF-8 zurückzudekodieren, braucht man ein UTF-8-Ziel. Ein einfaches CAST(@raw AS varchar(max)) in einer Datenbank mit der Standardsortierung SQL_Latin1_General_CP1_CI_AS zeigt héllo wörld. Fügt man die Bytes in eine Spalte ein, die als varchar(max) COLLATE Latin1_General_100_CI_AS_SC_UTF8 deklariert ist, erhält man héllo wörld. Für UTF-16-Daten genügt CAST(@raw AS nvarchar(max)).
Fehler
Mit einem String-Literal scheitert fehlerhaftes Base64 schon beim Kompilieren: Msg 9319: XQuery [value()]: Static simple type validation: Invalid simple type value 'aGk'. Dieselbe Eingabe über sql:variable liefert stattdessen NULL. Fehlendes Padding, URL-sichere Zeichen (PDw_Pz8-Pg==) und Padding-Bits ungleich null (aGl=) wurden alle abgelehnt; ein Zeilenumbruch im String wurde akzeptiert.
SQL Server 2025: BASE64_ENCODE und BASE64_DECODE
SQL Server 2025 (17.x) und Azure SQL bringen echte Funktionen mit, einschließlich eines URL-sicheren Flags:
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 nimmt nur varbinary; varchar scheitert mit Msg 8116: Argument data type varchar(max) is invalid for argument 1 of base64_encode function. BASE64_DECODE akzeptiert beide Alphabete, mit oder ohne Padding, und auch aGl=. Ungültige Eingaben wie aGk=!! oder a lösen Msg 9803: Invalid data for type "Base64Decode" aus.
Fallstricke in allen Datenbanken
- Zeichensatz der Eingabe. Derselbe Text ergibt in einer
latin1-Spalte, einerutf8mb4-Spalte und einernvarchar-Spalte unterschiedliches Base64. Entscheiden Sie sich für UTF-8-Bytes und wandeln Sie explizit um. - Versteckte Zeilenumbrüche. MySQL und PostgreSQL brechen nach 76 Zeichen um. JSON-Verarbeiter und HTTP-Header scheitern am eingebetteten
\n. - Stille
NULL-Werte. MySQL und der XML-Trick in SQL Server liefern bei fehlerhafter EingabeNULL, das einJOINoderWHEREstillschweigend verwirft. - Große Werte. Einen BLOB in einer Abfrage zu kodieren überträgt 33 % mehr Daten. Um einen gespeicherten Wert von Hand zu prüfen, selektieren Sie das Base64 und öffnen es mit Base64 in Datei oder Base64 in Hex.
Häufige Fragen
Warum liefert FROM_BASE64 in MySQL NULL?
MySQL liefert bei ungültiger Eingabe NULL statt eines Fehlers: bei fehlendem Padding, URL-sicheren - oder _ oder Fremdzeichen. Prüfen Sie die Eingabe mit dem Base64-Validator und korrigieren Sie URL-sichere Strings vor dem Dekodieren mit REPLACE.
Warum enthält die Ausgabe von TO_BASE64 in MySQL Zeilenumbrüche?
TO_BASE64 folgt der MIME-Konvention und fügt nach je 76 Zeichen einen Zeilenumbruch ein. Mit REPLACE(TO_BASE64(x), '\n', '') erhalten Sie eine einzeilige Ausgabe.
Hat SQL Server eine Base64-Funktion?
SQL Server 2025 und Azure SQL haben BASE64_ENCODE und BASE64_DECODE. Ältere Versionen haben keine Funktion, aber die XML-Umwandlung xs:base64Binary erledigt die Aufgabe.
Sollte ich Dateien als Base64 in der Datenbank speichern?
Meist nicht. Eine Binärspalte (BLOB, bytea, varbinary) speichert dieselben Daten etwa 25 % kleiner und spart die Umwandlung. Kodieren Sie nur, wenn Sie die Daten an ein System schicken, das Text braucht. Siehe Base64-Größenzuwachs.