Загрузить файл
  1. base64hub
  2. Base64 в коде
  3. SQL
Код

Base64 в SQL

Любая крупная СУБД умеет Base64, но у каждой свои имена функций и своё поведение при ошибках. Результаты ниже получены на MySQL 8.4, PostgreSQL 17 и SQL Server 2022 и 2025.

MySQL и MariaDB: TO_BASE64 и 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 кодирует байты строки в её кодировке. С utf8mb4 получится UTF-8, а столбец latin1 даст байты Latin-1, поэтому TO_BASE64(CONVERT('héllo' USING latin1)) возвращает aOlsbG8= вместо aMOpbGxv. FROM_BASE64 возвращает двоичную строку; обратно в текст её превращает CONVERT(... USING utf8mb4).

TO_BASE64 переносит строки через 76 символов, как 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

Ошибок на некорректных данных FROM_BASE64 не выдаёт, а возвращает NULL:

ВходРезультат
aGk=hi
aGkNULL (нет дополнения)
aGk=!!NULL
PDw_Pz8-Pg==NULL (URL-safe)
aNULL
aGl=hi (ненулевые биты дополнения допускаются)
'aGVs\nbG8K', 'aGVs bG8K'hello\n (пробельные символы игнорируются)

URL-safe преобразование строковыми функциями:

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)));
-- <<???>>

Для длинных значений оберните кодировщик ещё и в REPLACE(..., '\n', ''). Обе функции есть начиная с MySQL 5.6 и в MariaDB.

PostgreSQL: encode и decode

PostgreSQL работает с bytea. Текст переводите через convert_to, а обратно – через convert_from:

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

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

Как и в MySQL, encode(..., 'base64') переносит строки через 76 символов; psql показывает перевод строки как + в конце строки. Уберите его через replace(encode(x, 'base64'), E'\n', '').

В отличие от MySQL, на некорректных данных возникает ошибка:

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=!! падает с invalid symbol "!", а a – с invalid base64 end sequence. Пробельные символы, включая переводы строк и пробелы, игнорируются, а aGl= принимается.

В PostgreSQL 17 и 18 нет формата base64url (unrecognized encoding: "base64url"), поэтому преобразуйте через 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');
-- <<???>>

Чтобы проверять строки, не прерывая транзакцию, оберните decode в функцию на PL/pgSQL с блоком EXCEPTION WHEN others, который возвращает NULL.

SQL Server: трюк с XML base64Binary

До SQL Server 2025 функции для Base64 нет. Тип XML умеет преобразовывать между varbinary и xs:base64Binary, а это и есть 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 и FOR JSON тоже выводят столбцы varbinary в Base64: SELECT CAST('hi' AS varbinary(max)) AS bin FOR JSON PATH возвращает [{"bin":"aGk="}]. Преобразование через XML строки не переносит: 60 байт превратились в одну строку из 80 символов.

Методам XML нужен QUOTED_IDENTIFIER ON. В sqlcmd он по умолчанию выключен, и вы получите Msg 1934: SELECT failed because the following SET options have incorrect settings: 'QUOTED_IDENTIFIER'. Передайте -I или выполните SET QUOTED_IDENTIFIER ON.

Кодировка текста в SQL Server

nvarchar – это UTF-16LE, поэтому CAST(N'héllo wörld' AS varbinary(max)) кодируется в aADpAGwAbABvACAAdwD2AHIAbABkAA==, и другие системы декодируют это с промежутками между буквами. Чтобы получить UTF-8 (SQL Server 2019+), сначала пропустите строку через UTF-8 collation:

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==

Для обратного декодирования UTF-8 нужна цель в UTF-8. Обычный CAST(@raw AS varchar(max)) в базе с collation по умолчанию SQL_Latin1_General_CP1_CI_AS показывает héllo wörld. Если вставить байты в столбец, объявленный как varchar(max) COLLATE Latin1_General_100_CI_AS_SC_UTF8, получится héllo wörld. Для данных в UTF-16 достаточно CAST(@raw AS nvarchar(max)).

Ошибки

Если Base64 передан строковым литералом, плохая строка падает ещё на этапе компиляции: Msg 9319: XQuery [value()]: Static simple type validation: Invalid simple type value 'aGk'. Те же данные, переданные через sql:variable, вместо этого возвращают NULL. Отсутствие дополнения, URL-safe символы (PDw_Pz8-Pg==) и ненулевые биты дополнения (aGl=) были отвергнуты, а перевод строки внутри строки был принят.

SQL Server 2025: BASE64_ENCODE и BASE64_DECODE

В SQL Server 2025 (17.x) и Azure SQL появились полноценные функции, в том числе с флагом 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 принимает только varbinary; при передаче varchar получите Msg 8116: Argument data type varchar(max) is invalid for argument 1 of base64_encode function. BASE64_DECODE принимает оба алфавита, с дополнением и без, а также aGl=. На некорректных данных вроде aGk=!! или a возникает Msg 9803: Invalid data for type "Base64Decode".

Подводные камни во всех СУБД

  • Кодировка входных данных. Один и тот же текст даёт разный Base64 в столбце latin1, столбце utf8mb4 и столбце nvarchar. Договоритесь о байтах UTF-8 и преобразуйте явно.
  • Скрытые переводы строк. MySQL и PostgreSQL переносят строки через 76 символов. Потребители JSON и HTTP-заголовки ломаются на встроенном \n.
  • Молчаливые NULL. MySQL и трюк с XML в SQL Server возвращают NULL на плохих данных, а JOIN или WHERE такие строки тихо отбрасывают.
  • Большие значения. Кодирование BLOB в запросе гонит по сети на 33% больше данных. Чтобы вручную проверить сохранённое значение, выберите его в Base64 и откройте инструментом Base64 в файл или Base64 в hex.

Вопросы и ответы

Почему FROM_BASE64 в MySQL возвращает NULL?

На некорректных данных MySQL возвращает NULL вместо ошибки: при отсутствии дополнения, URL-safe символах - или _ и мусорных символах. Проверьте строку валидатором Base64, а URL-safe строки перед декодированием исправьте через REPLACE.

Почему в выводе TO_BASE64 в MySQL есть переносы строк?

TO_BASE64 следует соглашению MIME и вставляет перевод строки через каждые 76 символов. Для вывода в одну строку оберните вызов в REPLACE(TO_BASE64(x), '\n', '').

Есть ли в SQL Server функция для Base64?

В SQL Server 2025 и Azure SQL есть BASE64_ENCODE и BASE64_DECODE. В более старых версиях функции нет, но с задачей справляется преобразование через XML xs:base64Binary.

Стоит ли хранить файлы в базе в виде Base64?

Обычно нет. Двоичный столбец (BLOB, bytea, varbinary) хранит те же данные примерно на 25% компактнее и обходится без преобразований. Кодируйте только при передаче в систему, которой нужен текст. См. рост размера в Base64.

Читайте также