Enviar um arquivo
  1. base64hub
  2. Base64 no código
  3. SQL
Código

Base64 em SQL

Todo banco de dados importante sabe fazer Base64, cada um com seus nomes de função e seu jeito de falhar. Os resultados abaixo vêm do MySQL 8.4, do PostgreSQL 17 e do SQL Server 2022 e 2025.

MySQL e MariaDB: TO_BASE64 e FROM_BASE64

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

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

O TO_BASE64 codifica os bytes da string no conjunto de caracteres dela. Com utf8mb4 você obtém UTF-8; uma coluna latin1 dá bytes Latin-1, então TO_BASE64(CONVERT('héllo' USING latin1)) retorna aOlsbG8= em vez de aMOpbGxv. O FROM_BASE64 retorna uma string binária; o CONVERT(... USING utf8mb4) a transforma de volta em texto.

O TO_BASE64 quebra as linhas em 76 caracteres, como o 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

Entrada inválida não gera erro. O FROM_BASE64 retorna NULL:

EntradaResultado
aGk=hi
aGkNULL (sem preenchimento)
aGk=!!NULL
PDw_Pz8-Pg==NULL (URL-safe)
aNULL
aGl=hi (bits de preenchimento diferentes de zero aceitos)
'aGVs\nbG8K', 'aGVs bG8K'hello\n (espaços em branco ignorados)

Conversão URL-safe com funções de string:

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

Para valores mais longos, envolva também o codificador em REPLACE(..., '\n', ''). As duas funções existem desde o MySQL 5.6 e também no MariaDB.

PostgreSQL: encode e decode

O PostgreSQL trabalha com bytea. Converta texto com convert_to e volte com convert_from:

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

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

Como o MySQL, o encode(..., 'base64') quebra em 76 caracteres; o psql mostra a quebra de linha como um + no fim da linha. Remova-a com replace(encode(x, 'base64'), E'\n', '').

Ao contrário do MySQL, entrada inválida gera erro:

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=!! falha com invalid symbol "!", e a com invalid base64 end sequence. Espaços em branco, inclusive quebras de linha e espaços, são ignorados, e aGl= é aceito.

O PostgreSQL 17 e 18 não têm o formato base64url (unrecognized encoding: "base64url"), então converta com 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');
-- <<???>>

Para validar sem abortar uma transação, envolva o decode numa função PL/pgSQL com um bloco EXCEPTION WHEN others que retorne NULL.

SQL Server: o truque do XML base64Binary

Antes do SQL Server 2025 não existe função de Base64. O tipo XML converte entre varbinary e xs:base64Binary, que é 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

O FOR XML ... BINARY BASE64 e o FOR JSON também emitem colunas varbinary como Base64: SELECT CAST('hi' AS varbinary(max)) AS bin FOR JSON PATH retorna [{"bin":"aGk="}]. A conversão XML não quebra linhas: 60 bytes saíram como uma única string de 80 caracteres.

Os métodos XML exigem QUOTED_IDENTIFIER ON. O sqlcmd vem com essa opção desligada por padrão, o que dá Msg 1934: SELECT failed because the following SET options have incorrect settings: 'QUOTED_IDENTIFIER'. Passe -I ou execute SET QUOTED_IDENTIFIER ON.

Codificação de texto no SQL Server

nvarchar é UTF-16LE, então CAST(N'héllo wörld' AS varbinary(max)) vira aADpAGwAbABvACAAdwD2AHIAbABkAA==, que outros sistemas decodificam com espaços entre as letras. Para UTF-8 (SQL Server 2019+), passe antes por uma collation 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==

Para decodificar UTF-8 de volta, é preciso um destino UTF-8. Um CAST(@raw AS varchar(max)) simples num banco com a collation padrão SQL_Latin1_General_CP1_CI_AS mostra héllo wörld. Inserir os bytes numa coluna declarada como varchar(max) COLLATE Latin1_General_100_CI_AS_SC_UTF8 dá héllo wörld. Para dados UTF-16, CAST(@raw AS nvarchar(max)) basta.

Erros

Com um literal de string, Base64 inválido falha em tempo de compilação: Msg 9319: XQuery [value()]: Static simple type validation: Invalid simple type value 'aGk'. A mesma entrada passada por sql:variable retorna NULL. Falta de preenchimento, caracteres URL-safe (PDw_Pz8-Pg==) e bits de preenchimento diferentes de zero (aGl=) foram todos rejeitados; uma quebra de linha dentro da string foi aceita.

SQL Server 2025: BASE64_ENCODE e BASE64_DECODE

O SQL Server 2025 (17.x) e o Azure SQL trazem funções de verdade, inclusive com uma flag 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

O BASE64_ENCODE só aceita varbinary; passar varchar falha com Msg 8116: Argument data type varchar(max) is invalid for argument 1 of base64_encode function. O BASE64_DECODE aceita os dois alfabetos, com ou sem preenchimento, e também aGl=. Entrada inválida, como aGk=!! ou a, gera Msg 9803: Invalid data for type "Base64Decode".

Armadilhas em todos os bancos

  • Conjunto de caracteres da entrada. O mesmo texto dá Base64 diferente numa coluna latin1, numa utf8mb4 e numa nvarchar. Padronize em bytes UTF-8 e converta de forma explícita.
  • Quebras de linha escondidas. O MySQL e o PostgreSQL quebram em 76 caracteres. Consumidores de JSON e headers HTTP quebram com o \n embutido.
  • NULLs silenciosos. O MySQL e o truque do XML no SQL Server retornam NULL para entrada inválida, que um JOIN ou um WHERE descarta sem avisar.
  • Valores grandes. Codificar um BLOB numa consulta trafega 33% mais dados pela rede. Para conferir um valor armazenado à mão, selecione o Base64 e abra-o com Base64 para arquivo ou Base64 para hex.

Perguntas frequentes

Por que o FROM_BASE64 do MySQL retorna NULL?

O MySQL retorna NULL em vez de um erro quando a entrada é inválida: falta de preenchimento, - ou _ do URL-safe, ou caracteres de lixo. Confira a entrada com o validador de Base64 e corrija strings URL-safe com REPLACE antes de decodificar.

Por que a saída do TO_BASE64 do MySQL tem quebras de linha?

O TO_BASE64 segue a convenção MIME e insere uma quebra de linha a cada 76 caracteres. Envolva-o em REPLACE(TO_BASE64(x), '\n', '') para obter saída em uma linha.

O SQL Server tem uma função de Base64?

O SQL Server 2025 e o Azure SQL têm BASE64_ENCODE e BASE64_DECODE. As versões anteriores não têm função, mas a conversão XML xs:base64Binary resolve.

Devo guardar arquivos como Base64 no banco de dados?

Geralmente não. Uma coluna binária (BLOB, bytea, varbinary) guarda os mesmos dados cerca de 25% menores e dispensa a conversão. Codifique só quando for enviar os dados para um sistema que precisa de texto. Veja aumento de tamanho do Base64.

Continue lendo