Haben Sie mit dem Base64-Format zu tun? Dann ist diese Website genau das Richtige für Sie! Nutzen Sie unser superpraktisches Online-Tool, um Ihre Daten zu kodieren oder zu dekodieren.

Base64-Kodierung in SQL: Ein vollständiger Leitfaden

Von Zeit zu Zeit muss die Datenbank mit der Außenwelt sprechen, und die Außenwelt spricht nicht immer Bytes. Eine API will Ihr Logo in einem JSON-String. Ein Config-Export will ein Geheimnis, das auf eine Zeile YAML passt, ohne Anführungszeichen oder Backslashes. Ein Wartungsskript will eine Datei über ein System schicken, das nur Text trägt. Das ist der Moment, in dem Ihre Daten ein Kostüm aus Buchstaben anziehen, und der Name des Kostüms ist Base64.

Das Format selbst wurde auf der Startseite bereits abgedeckt (64 druckbare Zeichen, je vier davon stehen für drei Eingabe-Bytes, bis zu zwei =-Zeichen als Padding in der letzten Gruppe), also überspringt dieser Artikel diese Vorlesung und geht direkt zum Maschinen-Job. Zwei Dinge festhalten: Kodieren ist die Richtung, in der Daten größer werden, also spüren Spaltenbreiten und Paketlimits jedes einzelne Byte davon, und die Kodierer in dieser SQL-Familie sind sich uneinig über die zwei Dinge, die sich später am schwersten rückgängig machen lassen: welche Bytes sie lesen, wenn Ihre Spalte Text hält, und wohin sie die Zeilenumbrüche in dem setzen, was sie schreiben.

Der Kodierer-Cheatsheet

Wer Dienst hat, was sie essen, und wo sie ihre Ausgabe brechen. Die letzten zwei Spalten sind die, die beißen, denn ein String voller ungeladener Zeilenumbrüche und ein String mit einem anderen Alphabet sind beide vollkommen gültige Base64-Strings, die Ihr Konsument trotzdem ablehnen wird:

Dialekt Der Aufruf Eingangstyp Brecht bei 76 um? URL-sichere Option Seit wann
MySQL 8.x / MariaDB 10.x TO_BASE64(str) String (Zeichensatz gilt) ja keine MySQL 5.6 (2013)
PostgreSQL encode(bytea, 'base64') bytea ja, nur LF keine 7.2 (2002)
SQLite (CLI 3.41+) base64(blob) BLOB ja, bei 72 keine 3.41.0 (2023)
DuckDB to_base64(blob) BLOB nein keine aktuelle Versionen
ClickHouse 18.16+ base64Encode(x) alles, gecastet zu String nein base64URLEncode() 18.16 (2018)
SQL Server 2025+ BASE64_ENCODE(bin [, url_safe]) varbinary nein zweites Argument 2025
Oracle UTL_ENCODE.BASE64_ENCODE(raw) RAW nein keine 9i-Zeit
Snowflake BASE64_ENCODE(binary) BINARY nein keine aktuelle Versionen

Lesen Sie die Tabelle von links nach rechts, und die Arbeit fällt in zwei Entscheidungen. Erstens, wie Ihre Bytes dorthin kommen: Die Eingangstyp-Spalte ist der Ort, wo Zeichensatz-Überraschungen geboren werden, denn "derselbe Text" sind unter verschiedenen Kollationen verschiedene Bytes. Zweitens, was auf der anderen Seite herauskommt: Die Umbruch-Spalte entscheidet, ob Ihr Ergebnis eine flache Zeile ist oder ein Gedicht mit einem Zeilenumbruch alle 76 Zeichen, und die URL-sichere Spalte entscheidet, ob Sie das Ergebnis überhaupt in einen Link setzen können.

Zunächst: Entscheiden Sie, welche Bytes Sie meinen

Ein Kodierer packt Bytes, aber Ihre Spalte hält normalerweise Buchstaben, und Buchstaben sind nur Bytes, wenn Sie sagen, welches Alphabet der Bytes. MySQLs TO_BASE64() liest sein Argument im Verbindungs-Zeichensatz, was eine Bequemlichkeit ist, bis es keine ist: Dasselbe 'héllo' reist als anderes Base64 unter einem latin1-Client und einem utf8mb4-Client. Wenn Sie die exakten Bytes wie gespeichert meinen, frieren Sie sie zuerst mit einem binären Cast ein:

SELECT TO_BASE64('hello') AS from_text;
SELECT TO_BASE64(CAST('héllo' AS BINARY)) AS utf8_bytes;

Die zweite Zeile kommt als aMOpbGxv zurück, wobei die zwei Hex-Bytes C3 A9 in der Mitte die Art von UTF-8 sind, é zu buchstabieren. PostgreSQL ist von vorneherein strenger: encode() weigert sich, auf irgendetwas zu schauen, das kein bytea ist, also muss ein Textwert zuerst seine Kodierung benennen, während rohe Bytes als Hex-Literal ankommen können:

SELECT encode(convert_to('héllo', 'UTF8'), 'base64') AS text_as_utf8;
SELECT encode('\x68656c6c6f'::bytea, 'base64') AS raw_bytes;

Jeder andere Dialekt hat seine eigene Fronttür zu derselben Idee, und sie reduzieren sich alle auf "Hole die Bytes, dann pack sie":

Dialekt Text zu Bytes Der Kodierer-Aufruf
T-SQL CAST('héllo' AS VARBINARY(8000)) über die Kollation der Spalte BASE64_ENCODE(bin)
Snowflake TO_BINARY('héllo', 'UTF-8') BASE64_ENCODE(binary)
Oracle UTL_RAW.CAST_TO_RAW('héllo') UTL_ENCODE.BASE64_ENCODE(raw)
DuckDB encode('héllo') ergibt einen BLOB to_base64(blob)
SQLite CLI ein BLOB-Literal wie X'68656C6C6F' base64(blob)

Die praktische Regel ist dieselbe wie auf der Dekodier-Seite: Entscheiden Sie den Zeichensatz, bevor Sie kodieren, schreiben Sie ihn als Literal in die Abfrage und lassen Sie eine einzige akzentuierte Payload durch die ganze Pipeline laufen, bevor Sie der Spalte trauen. Ein einziges héllo fängt jede falsche Kollation, und es kostet nichts.

Danach: Beobachten Sie, was herauskommt

Sobald die Bytes gepackt sind, gehen die Kodierer beim Thema Zeilenumbrüche getrennte Wege. Drei von ihnen brechen die Ausgabe um: MySQL und PostgreSQL bei 76 Zeichen, die E-Mail-Gewohnheit, und die SQLite-CLI bei 72; die restlichen geben eine flache Zeile zurück, egal wie lange sie wird. Der Unterschied ist leicht zu übersehen und teuer zu finden, denn ein Base64-Feld mit versteckten Zeilenumbrüchen ist ein Feld, das einen JSON-Parser mitten drin zum Brechen bringt:

SELECT LENGTH(TO_BASE64(REPEAT('x', 300))) AS wrapped,
      LENGTH(REPLACE(TO_BASE64(REPEAT('x', 300)), '\n', '')) AS flat;

Dreihundert Eingabe-Bytes kommen als 400 Base64-Zeichen zurück, und derselbe Aufruf misst 405, weil fünf Zeilenumbrüche mitgefahren sind. Die Arithmetik dahinter ist klein genug, um sie im Kopf zu behalten: Die flache Länge ist die Eingabelänge, geteilt durch drei, aufgerundet, mal vier. Wenn Ihr Kodierer umbreicht, fügen Sie zwischen den 76-Zeichen-Zeilen einen Zeilenumbruch hinzu, das ist die flache Länge, geteilt durch 76 und aufgerundet, minus eins. Dreihundert Bytes: 400 flach, 405 umgebrochen. Einhundertelf Bytes: 148 flach, 149 umgebrochen. Ein Zeilenumbruch mehr, als Sie eingeplant haben, ist der Weg, wie eine VARCHAR(500)-Spalte anfängt, eine VARCHAR(480)-Payload still abzuschneiden.

Zwei Konsequenzen, die es sich zu notieren lohnt. Dimensionieren Sie Textspalten für die flache Länge plus ein wenig Spielraum, wenn der Schreiber umbrechen könnte, oder verbieten Sie den Umbruch im Schreiber und dimensionieren Sie für flach. Und denken Sie daran, dass die Grenze, gegen die Ihr Ergebnis kämpft, die Grenze des Strings ist, nicht der Bytes: In MySQL zählt der umgebrochene Text gegen max_allowed_packet (64 MB Standard in MySQL 8), also passt ein 50-Megabyte-Foto, kodiert zu rund 67 Megabyte Buchstaben, nicht in das Standard-Paket, obwohl die rohe Datei es würde.

URL-sicheres Base64: Das reisende Alphabet

Abschnitt 5 von RFC 4648 definierte ein zweites Alphabet für Base64, weil das ursprüngliche zwei Zeichen hat, die in der URL-Syntax Jobs haben. Das Pluszeichen fügt Query-Parameter hinzu, der Schrägstrich trennt Pfadsegmente, und das Padding-Gleichheitszeichen wird prozent-kodiert, in dem Moment, in dem es auf einen Query-String trifft. Die URL-sichere Variante tauscht + gegen - und / gegen _, und die JWT-Spezifikation lässt darüber hinaus das Padding ganz fallen, so dass ein Token in einem Link, einem Pfadsegment oder einem Dateinamen sitzen kann, ohne ein einziges Prozentzeichen.

Nur ein Dialekt in dieser Familie liefert den Schalter nativ. SQL Server 2025s BASE64_ENCODE() nimmt ein optionales zweites Argument entgegen, und wenn es an ist, benutzt das Ergebnis - und _ und überspringt das Padding:

SELECT BASE64_ENCODE(0xCAFECAFE) AS standard;
SELECT BASE64_ENCODE(0xCAFECAFE, TRUE) AS url_safe;

Dieselben vier Bytes kommen als yv7K/g== und yv7K_g zurück. ClickHouse hält die Varianten als separate Funktionen, und seine URL-sichere Form lässt auch das Padding fallen:

SELECT base64URLEncode('https://clickhouse.com') AS url_safe;

das als aHR0cHM6Ly9jbGlja2hvdXNlLmNvbQ ankommt, die zwei Padding-Zeichen der Standardform abgeschnitten. Überall sonst ist das Rezept zwei Zeichenübersetzungen und ein Abschneiden, und es lohnt sich, es einmal als Datenbankfunktion zu schreiben, denn jede Token-Pipeline braucht es. In PostgreSQL liest es sich so:

SELECT rtrim(replace(replace(
        encode(convert_to('https://clickhouse.com', 'UTF8'), 'base64'),
        '+', '-'),
      '/', '_'),
      '=') AS url_safe;

Übersetzen Sie + zu -, / zu _, schneiden Sie das nachfolgende Padding ab, fertig. Eine Warnung für die SQL-Server-Menge: Die url_safe-Ausgabe ist nicht das, was die eigenen XML- und JSON-Base64-Dekodierer des Servers erwarten, also wird eine Spalte, die in URL-sicherer Form für die Außenwelt gepackt wurde, nicht mit den Eingebauten innerhalb der Datenbank ausgepackt. Halten Sie das Publikum im Kopf, bevor Sie das Alphabet wählen.

JWTs: Tokens aus der Datenbank prägen

Das Interessanteste, das Sie mit dem Kodierer bauen können, ist ein JSON Web Token, denn ein JWT ist nichts anderes als drei Base64-Stücke in einer Reihe: ein Header und eine Payload, beide JSON-Objekte, URL-sicher ohne Padding gepackt, und eine Signatur, die über den ersten zwei berechnet wird. Wenn ein Batch-Job Tokens prägen muss (eine Testumgebung säen, abgelaufene API-Zugangsdaten neu erzeugen, einen Audit-Feed bauen), passt die ganze Zeremonie in eine PostgreSQL-Abfrage, wenn Sie pgcrypto für den HMAC akzeptieren (aktivieren Sie sie einmal mit CREATE EXTENSION IF NOT EXISTS pgcrypto;):

WITH head AS (
  SELECT encode(convert_to('{"alg":"HS256","typ":"JWT"}', 'UTF8'), 'base64') AS h
),
body AS (
  SELECT encode(convert_to('{"sub":"1234567890","name":"Dev User"}', 'UTF8'), 'base64') AS p
),
joined AS (
  SELECT rtrim(replace(replace(h, '+', '-'), '/', '_'), '=') AS h64u,
         rtrim(replace(replace(p, '+', '-'), '/', '_'), '=') AS p64u
  FROM head, body
)
SELECT h64u || '.' || p64u || '.' ||
       rtrim(replace(replace(
         encode(hmac((h64u || '.' || p64u)::bytea, 'sql-secret-key'::bytea, 'sha256'), 'base64'),
         '+', '-'),
         '/', '_'),
       '=') AS token
FROM joined;

Jeder Schritt ist einer der Züge, die dieser Artikel bereits gezeigt hat: Das JSON als Base64 packen, es in das URL-sichere Alphabet ohne Padding formen, dann die ersten zwei Stücke signieren und die Signatur auf dieselbe Art formen. Für das JSON oben und das Geheimnis sql-secret-key ist das Ergebnis eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkRldiBVc2VyIn0.7_3VdmM8vH0L2bRBNqXXQXzZIR1l8T4_S4QxPPNBEFM, ein Token, das jeder HS256-Prüfer akzeptiert. Die Warnungen verdienen genauso viel Sendezeit wie der Trick: Es deckt nur HMAC-Algorithmen ab (HS256, HS384, HS512), legt ein gemeinsames Geheimnis in eine Datenbank-Anweisung und ist für Batch- und Audit-Arbeit gebaut, nicht für einen Produktions-Token-Dienst. Die Verifizierungs-Seite, wo Sie dieses Token gegenüber seinem Geheimnis beweisen, ist ein Job für die Anwendungsschicht oder für die Signaturprüfung des Dekodierungs-Artikels.

Bilder und Dateien in einer Textspalte

Der häufigste Grund, in SQL zu kodieren, ist eine Datei, die als Text reisen muss: eine API, die das Bild inline einbettet statt es zu referenzieren, ein Export für ein System, das kein Binärfeld trägt, ein Seed-Skript, das eine Datenbank auf einem neuen Server neu erstellt. DuckDB macht die Rundstrecke beinahe trivial, denn es liest Dateien durch eine Tabellenfunktion, die Glob-Muster annimmt, in BLOBs, und der Kodierer glättet, was auch immer ankommt:

SELECT filename, to_base64(content) AS b64
FROM read_blob('/data/pics/*.png');

Eine Zeile pro Datei, ein flacher Base64-String pro Zeile, kein Umbruch zum Entfernen, obwohl die üblichen ein oder zwei Padding-Zeichen am Ende mitfahren. Schreiben Sie das Ergebnis in eine Textspalte, und die Bilder sind portabel durch jeden Kanal, der Text bewegt. Dann führen Sie die Kosten-Unterhaltung ehrlich: Ein 1-Megabyte-Foto kommt als rund 1,33 Megabyte Buchstaben an, und ab dann zahlt jeder Scan, jedes Sortieren und jeder Index-Eintrag diesen Preis. Wenn Sie das Schema kontrollieren, ist das bessere Design eine BLOB-Spalte plus ein Kodieren an der API-Grenze, wo nur die Bytes verkleidet werden, die das Gebäude tatsächlich verlassen.

HTTP, JSON und API-Verkehr

Header und Payloads sind der Ort, an dem Base64 seine leise Alltagsarbeit verrichtet. Ein Basic-Auth-Header ist das wörtliche Präfix Basic gefolgt vom Base64 von username:password, und das Konstruieren eines in SQL ist eine Konkatenation plus ein Kodieren:

SELECT 'Basic ' || encode(convert_to('alice' || ':' || 's3cret', 'UTF8'), 'base64') AS header;

das Basic YWxpY2U6czNjcmV0 baut, den exakten Header, den ein Client senden würde. Nutzen Sie es, um die Fixtures zu erzeugen, mit denen Ihre Integrationstests vergleichen, oder um eine Spalte gespeicherter Header zu normalisieren, bevor Sie sie auditieren. Auf der JSON-Seite kann MySQL ein Feld packen und es in einem einzelnen Ausdruck in ein Dokument einbetten, kein Anwendungscode im Spiel:

SELECT JSON_OBJECT('img', TO_BASE64(CAST('hello file' AS BINARY))) AS doc;

Das Ergebnis ist {"img": "aGVsbG8gZmlsZQ=="}, eine versandfertige Payload. Dieselbe Form funktioniert für Zertifikate, öffentliche Schlüssel und jede andere Datei, die Ihre API inline einbetten entschieden hat, und es ist die Richtung, die zählt, wenn Sie derjenige sind, der den Verkehr produziert, nicht der, der den von jemand anderem dekodiert.

Config-Dateien, Geheimnisse und Umgebungsvariablen

Eine Export-Gewohnheit verdient einen eigenen Absatz, denn sie ist überall: das Geheimnis, das als Base64 in einer Config-Tabelle gespeichert wird. Kubernetes hat die Gewohnheit am Leben gehalten, wo Geheimnis-Werte im Ruhezustand Base64 sind, damit sie auf eine Zeile YAML passen, ohne Anführungszeichen, ohne Zeilenumbrüche und ohne Backslashes, und jedes hausgemachte Config-System, das je auf eine Kubernetes-Pipeline traf, hat sie übernommen. Die Pack-Richtung ist ein Kodieren pro Wert, wobei der binäre Cast die Zeichensatz-Arbeit erledigt, damit der exportierte Text genau die gespeicherten Bytes sind:

SELECT name, TO_BASE64(CAST(value AS BINARY)) AS for_config
FROM app_config
WHERE name LIKE '%_secret%';

Jeder Wert bis zu 57 Bytes kommt als flacher, einfügbereiter String heraus; alles Längere braucht ein REPLACE(), um die Umbruch-Zeilen zu entfernen, bevor es in YAML geht, und die neue Umgebung dekodiert es auf der anderen Seite zurück. Behandeln Sie das Ergebnis mit der Sorgfalt, die es verdient: Sie haben gerade eine Spalte gespeicherter Geheimnisse in eine Spalte gespeicherter Geheimnisse verwandelt, die jeder Mensch in etwa zehn Sekunden lesen kann, und die Base64-in-Config-Gewohnheit bekommt einen zweiten Blick, in dem Moment, in dem Sie so nah am Klartext stehen. Base64 ist ein Transport, kein Tresor. Wenn die Umgebung einen echten Secret-Store hat, ist die Base64-Spalte eine Migration davon weg.

E-Mail und die 76-Zeichen-Gewohnheit

Der 76-Zeichen-Umbruch ist älter als jede Datenbank auf dieser Seite. MIME, der Satz an Standards, der E-Mails binäre Anhänge tragen lässt (RFC 2045, Abschnitt 6.8, 1996), bricht die Base64-Ausgabe bei 76 Zeichen um und beendet jede Zeile mit einem Wagenrücklauf und einem Zeilenumbruch, weil das alte E-Mail-Netzwerk mit längeren Zeilen nicht zu trauen war. Drei Kodierer hier haben den Umbruch als ihren Standard geerbt (MySQL, PostgreSQL, die SQLite-CLI), was ein Geschenk ist für alles, was am Ende in einer E-Mail landete, und eine Falle für alles, was nicht. Und sie haben ihn halb fertig geerbt: PostgreSQL beendet seine Zeilen mit einem einzelnen Zeilenumbruch, nicht mit dem Wagenrücklauf und Zeilenumbruch, den der MIME-Standard vorgibt, also braucht Ausgabe, die in einen echten E-Mail-Anhang eingefügt werden soll, einen weiteren Durchgang:

WITH t AS (
 SELECT replace(encode(attachment::bytea, 'base64'), chr(10), '') AS s
 FROM email_outbox
)
SELECT regexp_replace(s, '(.{1,76})', '\1' || chr(13) || chr(10), 'g') AS mime_ready
FROM t;

Entfernen Sie die Zeilenumbrüche, die PostgreSQL bereits hinzugefügt hat, brechen Sie dann bei 76 mit einem vollen CRLF nach jeder Zeile neu um, und der String ist MIME-korrekt in einem Ausdruck. Lassen Sie dreihundert Bytes durch laufen, und die 400 Zeichen, die Sie gepackt haben, werden zu 412: sechs umgebrochene Zeilen, sechs CRLF-Paare, zwölf Zeichen Transport-Zeremonie. Dasselbe Problem in derselben Form zeigt sich bei PEM-Blöcken, die bei 64 statt 76 umbrechen, und bei den APIs, die gar keinen Umbruch wollen, weil ihr JSON-Parser keinen Zeilenumbruch mitten in einem Feld trifft. Die Regel für alle: Finden Sie heraus, welchen Vertrag der Konsument unterschrieben hat, bevor Sie kodieren, denn das Neueinpacken einer Spalte gespeicherten Base64 ist eine Migration, keine Abfrage.

Fallen: Wo Kodierer Sie belügen

Jede Falle auf dieser Liste ist eine, die ein bestimmter Dialekt stellt, keine, die Base64 stellt, und jede von ihnen hat mindestens eine Codebase, die sie in Produktion gefunden hat:

  • Der nicht-gewünschte Umbruch. MySQL und PostgreSQL brechen ihre Ausgabe standardmäßig bei 76 um, die SQLite-CLI bei 72, und niemand in Ihrer Abfrage hat danach gefragt. Das Base64-Feld in Ihrem JSON enthält jetzt Zeilenumbrüche, und der Konsument, der das Format in der Spezifikation akzeptiert, lehnt es in der Wildnis ab. Die flache Form ist ein REPLACE() über das Zeilenumbruch-Zeichen, angewandt auf der Schreiber-Seite, damit die Spalte speichert, was der Leser will.
  • Der Zeichensatz-Ausrutscher. TO_BASE64('héllo') ohne den binären Cast kodiert, was das Verbindungs-Zeichensatz für die Buchstaben hält, und ein latin1-Client und ein utf8mb4-Client halten verschiedene Dinge. Derselbe Abfrage-Text, zwei verschiedene Base64-Ergebnisse, und das Falsche dekodiert zu Mojibake, das niemand auf den Kodierer zurückverfolgt. Der binäre Cast, oder ein explizites convert_to(), ist die einzige ehrliche Version der Abfrage.
  • Die BLOB-Tür. DuckDBs to_base64() will einen BLOB: Geben Sie ihm Text, und er castet implizit, also kann eine varchar-Spalte mit einer nicht-UTF-8-Kodierung still die falschen Bytes kodieren. Der ehrliche Weg ist to_base64(encode(...)), und deshalb zeigen die Beispiele auf dieser Seite das Paar immer für Texteingabe.
  • Die 26.7-Leerraum-Änderung. ClickHouses base64Decode() und base64URLDecode() waren jahrelang streng bei der Eingabe, aber ab 26.7 ignorieren sie Leerräume (Leerzeichen, Tab, Zeilenumbruch, Wagenrücklauf, Formfeed) statt sie abzulehnen, also hat ein Skript, das früher bei einer umgebrochenen Spalte einen Fehler warf, jetzt still Erfolg, was seine eigene Art von Regression ist. Prüfen Sie die Server-Version, bevor Sie dem Dekodieren trauen.
  • Die 6000-Byte-Grenze. SQL Servers BASE64_ENCODE() gibt varchar(8000) zurück, wenn die Eingabe ein varbinary(n) mit n von 6000 oder weniger ist, und varchar(max) darüber; die Zuordnung schaut auf die deklarierte Größe, nicht auf den Wert, also gibt eine varbinary(8000)-Spalte varchar(max) zurück, selbst bei drei Bytes. Die url_safe-Ausgabe derselben Funktion ist derweil nicht lesbar für die eigenen XML- und JSON-Base64-Dekodierer des Servers, die das Standardalphabet mit Padding erwarten. Wählen Sie die Variante für das Publikum, das sie lesen wird.
  • Das 2000-Byte-RAW. In Oracle erreicht ein RAW-Wert in einer reinen SQL-Anweisung höchstens 2000 Bytes. Da der Kodierer RAW nimmt und RAW zurückgibt, kann ein Ein-Anweisung-Kodieren nur etwa 1500 Bytes Eingabe annehmen (2000 Zeichen an Ausgabe würden passen, mehr nicht), und ein Ein-Anweisung-Dekodieren kann nur 2000 Zeichen Base64 annehmen. Größere Payloads ziehen nach PL/SQL, wo eine RAW-Variable 32767 Bytes hält und ein einzelner Aufruf den Großteil davon trägt, und nur Payloads, deren Base64-Ausgabe diese Decke überschreiten würde, brauchen die Chunk-Schleife, die von dem 1990er-Limit stammt, das sich nie bewegt hat.
  • Die Paketsteuer. MySQL zählt den kodierten String gegen max_allowed_packet, nicht die rohen Bytes. Ein Foto, das die Tabelle mit Meilen Abstand passt, kann das Paket überlaufen, sobald es 33 Prozent größer und umgebrochen ist, und das Fehlerszenario ist ein abgeschnittener Wert oder ein NULL, das wie Datenkorruption aussieht. Prüfen Sie das Limit im selben Atemzug wie die Spaltenbreite.
  • Der nachfolgende Zeilenumbruch. Die base64() der SQLite-CLI beendet ihre letzte Zeile mit einem Zeilenumbruch, die Zeilenende-Gewohnheit, angewandt auch auf die finale Zeile. Kleben Sie die Shell-Ausgabe in ein JSON-Feld, und Sie haben einen Base64-String mit einem Zeilenumbruch darin versendet, der nicht-gewünschte Umbruch in einem anderen Hut.
  • Die Alphabet-Annahme. Ein Konsument, der für das Standardalphabet gebaut ist, trifft auf Ihre URL-sichere Ausgabe (oder umgekehrt) und sieht Zeichen, die er nicht kennt. Die meisten Dekodierer scheitern laut auf dem Unterstrich; ein paar scheitern still, indem sie ihn überspringen. Dokumentieren Sie das Alphabet jeder Base64-Spalte im Schema-Kommentar, denn der nächste Entwickler wird sich nicht erinnern, welche Token-Pipeline die Zeile geschrieben hat.

Wenn Größe wirklich zählt

Die Größenrechnung ist die flache Länge plus alles, was Ihr Kodierer an Umbruch hinzufügt, und die Startseite macht die volle Herleitung des Verhältnisses. Was sich hier zu tun lohnt, ist das Durchgehen, wo die Zahl aufhört, eine Kuriosität zu sein. Eine VARCHAR-Spalte, dimensioniert auf die Byte-Anzahl der Eingabe, schneidet die Ausgabe still ab, das erste Mal, wenn die Payload lang genug ist, um zusätzlichen Spielraum zu brauchen, denn drei Eingabe-Bytes kosten vier Zeichen. Ein Index über einer Base64-Textspalte zahlt die Steuer doppelt: einmal in der Speicherung und nochmal in jedem Vergleich, denn die Index-Einträge sind die umgebrochenen Buchstaben, nicht die Bytes. MySQLs max_allowed_packet und PostgreSQLs 1-GB-bytea-Decke sind die zwei Wände, die die meisten zuerst treffen, und beide werden gegen den Text geprüft, der die größere Seite des Geschäfts ist. Die Design-Antwort dreht sich selten darum, einen anderen Kodierer zu wählen (es gibt nur ein Base64); sie dreht sich darum, zu wählen, wo das Kodieren passiert. BLOB-Spalte, Hash-Spalte für Lookups, Kodieren an der Grenze: Das Base64 existiert nur im Verkehr, wo es hingehört.

Sicherheit: Was Base64 nicht ist

Base64 ist keine Verschlüsselung, und die eine Gewohnheit, die laut ausgesprochen werden muss, ist die Config-Tabelle-Eine von früher: Ein Geheimnis, das als Base64 gespeichert ist, ist ein Geheimnis, das in einer anderen Schriftart gespeichert ist. Die Transformation ist eine Bijektion ohne Schlüssel, rückgängig machbar von jeder Programmiersprache auf der Erde in einem Funktionsaufruf, und ihr einziger echter Effekt ist, den Wert auf einer Zeile YAML zu halten. Wenn das Bedrohungsmodell einen anderen Benutzer dieser Datenbank einschließt, einen anderen Dienst, der den Export liest, oder ein Log, das die Zeile erfasst hat, bringt Base64 exakt null zum Schutz bei. Es verschleiert den Wert vor dem menschlichen Auge für ein paar Sekunden, und deshalb fühlt es sich in einer Code-Review wie Schutz an, und deshalb scheitert es in einem Vorfall. Verschlüsseln Sie, was geheim sein muss, verschlüsseln Sie es mit einem Schlüssel, den jemand tatsächlich geheim halten kann, und lassen Sie Base64 den Job machen, den es gut kann: Bytes durch einen Kanal bewegen, der nur Text trägt.

Wann jeder Dialekt das Umbrechen lernte

Die Release Notes erzählen dieselbe Geschichte wie die Dekodier-Seite, nur mit den Buchstaben in die andere Richtung, und der Zeitplan sagt etwas über jede Engine:

2002. PostgreSQL 7.2 listet base64 als First-Class-Format von encode() und decode(), zeitgenössisch mit Oracles UTL_ENCODE in der 9i-Ära, und die älteste Base64-Maschinerie in dieser Familie mit knapper Marge. Eine Datenbank mit einem echten Binärtyp und einem Format-Argument war früh da, denn die Antwort war ein enum-Wert entfernt.

Anfang 2000er. Oracles UTL_ENCODE-Paket wird in der 9i-Ära ausgeliefert, mit BASE64_ENCODE() neben seinen MIME-Header-, quoted-printable- und uuecode-Brüdern. RAW hinein, RAW heraus, und ein Vierteljahrhundert später hat das Paket seine Meinung nicht geändert.

2013. MySQL 5.6 fügt TO_BASE64() und FROM_BASE64() als abgestimmtes Paar hinzu, und MariaDB 10.0 erbt beide. Der Vertrag des Paars hat sich seither nicht bewegt: 76-Zeichen-Zeilen auf dem Weg raus, Leerraum-Toleranz auf dem Weg rein.

2018. ClickHouse 18.16 (Dezember 2018) liefert base64Encode() und base64Decode() zusammen mit dem MySQL-artigen Alias aus, weil die säulenorientierte Welt Workloads importierte, deren Log-Schemas bereits Base64 in sich trugen.

2023. SQLite 3.41.0 fügt base64() der Kommandozeilen-Shell als anwendungsdefinierte Funktion hinzu. Die Kernbibliothek bekommt nichts, wie es ihre Art ist; die Shell, wo Menschen tatsächlich in SQLite-Dateien herumstochern, bekommt das Werkzeug.

2025. SQL Server 2025, der im November 2025 allgemein verfügbar wurde, liefert endlich BASE64_ENCODE() und BASE64_DECODE() aus, sechsunddreißig Jahre nach dem Produktstart und eine Generation, nachdem seine Nutzer den XML-Workaround auswendig gelernt hatten.

Das Muster ist dasselbe, mit dem der Dekodierungs-Artikel endet, gespiegelt: Die Engines mit einem echten Binärtyp und einem Format-Argument bekamen Base64 an dem Tag, an dem der Bedarf offensichtlich war, und die Engines, wo alles ein String ist, haben es für später eingeplant.

Seltsamkeiten, die es zu wissen lohnt

  • Die base64() der SQLite-CLI ist der Formwandler der Familie, und in der Kodier-Richtung zeigt sie den Trick am besten: Geben Sie ihm einen BLOB, und er gibt umgebrochenen Text mit nachfolgendem Zeilenumbruch zurück, geben Sie ihm Text, und er gibt einen BLOB zurück. Ein Name, zwei Jobs, gewählt nach dem Typ des Arguments, und kein anderer Kodierer in dieser Familie wird das.
  • ClickHouses base64Decode()-Familie wurde in 26.7 nachsichtig: Leerräume in der Eingabe werden jetzt ignoriert statt abgelehnt, also scheitert dieselbe Abfrage auf einer umgebrochenen Spalte auf dem alten Server und gibt still einen Wert zurück auf dem neuen. Der Dekodierer ist nicht kaputtgegangen; er ist gelockert, was irgendwie schwerer zu debuggen ist.
  • PostgreSQL bricht bei 76 Zeichen um, genau wie der MIME-Standard von 1996, nur dass er die Zeilen mit einem einzelnen Zeilenumbruch beendet statt mit dem Wagenrücklauf und Zeilenumbruch des Standards. Mehr als zwanzig Jahre nach der Spezifikation, ein Zeichen weniger pro Zeile, und der Aufstand ist unsichtbar, wenn Sie die Bytes nicht diffen.
  • Im mysql-Client geben die Bytes, die Sie kodieren, als Base64-Text fein aus, aber im Moment, in dem Sie die rohe Spalte mit CAST(... AS BINARY) ansehen, wechselt der Client zur Hex-Anzeige (binary-as-hex), und ein völlig gutes hello kommt auf dem Bildschirm als 0x68656C6C6F an. Die Einstellung hat Tausende von Entwicklern davon überzeugt, dass ihr Kodierer kaputt ist.
  • Snowflake zeigt BINARY-Werte in jedem Ergebnis-Set als Hex an, also liest sich eine TO_BINARY()-Eingangsspalte in Ihrer Kodier-Abfrage wie eine Prüfsumme, selbst wenn alles funktioniert hat. Zwei Dialekte, zwei Hex-Anzeigen, ein identisches Gefühl des Unbehagens.
  • Oracles SQL-Ebenen-RAW ist auf 2000 Bytes gedeckelt, also kann ein 3-Kilobyte-Zertifikat überhaupt nicht in eine SQL-Anweisung als RAW-Literal eingefügt werden. Das Kodieren muss in PL/SQL passieren, wo eine RAW-Variable 32767 Bytes hält, also ist das 3-Kilobyte-Zertifikat ein einzelner Aufruf, und nur Payloads, deren Base64-Ausgabe 32 Kilobyte überschreiten würde, brauchen die Chunk-Schleife, die aus den 1990ern stammt.
  • Eine Zeile MIME-Base64 ist 76 Zeichen, was 57 rohe Bytes sind, denn vier Zeichen tragen drei. Die Zahl 76, die in den Standards von drei Kodierern auftaucht, ist weniger eine Grenze als eine Packungsdichte: Jede umgebrochene Zeile, die Sie in einem alten E-Mail-Anhang sehen, trug genau 57 Bytes Ihrer Daten.

Die andere Richtung

Dieser Artikel hat sich damit beschäftigt, das Kostüm anzuziehen: zu entscheiden, welche Bytes Sie meinen, zu beobachten, was herauskommt, das Alphabet für das Publikum zu wählen und die Größenrechnung zu machen, bevor die Spalte abschneidet. Das Kostüm auszuziehen ist ein ganz anderes Temperament, mit stillen NULLs, wo ein Dialekt die Achseln zuckt, harten Fehlern, wo ein anderer die Stimme erhebt, und einem URL-sicheren Alphabet, das die Hälfte der Familie gar nicht kennt. All das, von FROM_BASE64() bis decode() bis BASE64_DECODE(), wird in dem verwandten Base64-Dekodierungs-Artikel für SQL im Detail behandelt, verlinkt direkt unten. Kodieren Sie hier, dekodieren Sie dort, und die ganze Rundstrecke passt in einen Nachmittag.

Zuletzt aktualisiert: 2026-09-08

Verwandter Artikel: Base64-Dekodierung in SQL: Ein vollständiger Leitfaden