ファイルを選択
  1. base64hub
  2. 各言語での Base64
  3. SQL
コード

SQL での Base64

主要なデータベースはどれも 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)) は aMOpbGxv ではなく aOlsbG8= を返します。FROM_BASE64 はバイナリ文字列を返すので、CONVERT(... USING utf8mb4) でテキストに戻します。

TO_BASE64 は MIME と同様に 76 文字で行を折り返します。

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セーフ)
aNULL
aGl=hi(0 でないパディングビットも受理)
'aGVs\nbG8K'、'aGVs bG8K'hello\n(空白は無視)

文字列関数による URLセーフへの変換:

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 関数で包み、NULL を返す EXCEPTION WHEN others ブロックを付けてください。

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 文字の 1 つの文字列になりました。

XML メソッドには QUOTED_IDENTIFIER ON が必要です。sqlcmd のデフォルトは OFF なので、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 の照合順序を経由します。

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 の受け皿が必要です。デフォルトの照合順序 SQL_Latin1_General_CP1_CI_AS のデータベースで単に CAST(@raw AS varchar(max)) とすると、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セーフの文字(PDw_Pz8-Pg==)、0 でないパディングビット(aGl=)はいずれも拒否され、文字列内の改行は受け付けられました。

SQL Server 2025:BASE64_ENCODE と BASE64_DECODE

SQL Server 2025(17.x)と Azure SQL には、URLセーフのフラグを含む本物の関数が追加されています。

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" が発生します。

データベース共通の落とし穴

  • 入力の文字セット。 同じテキストでも、latin1 の列、utf8mb4 の列、nvarchar の列では異なる Base64 になります。UTF-8 のバイト列に統一し、明示的に変換してください。
  • 隠れた改行。 MySQL と PostgreSQL は 76 文字で折り返します。埋め込まれた \n で、JSON の利用側や HTTP ヘッダーが壊れます。
  • 黙って返される NULL。 MySQL と SQL Server の XML による方法は不正な入力に NULL を返し、JOIN や WHERE で何も言わずに除外されます。
  • 大きな値。 クエリ内で BLOB をエンコードすると、ネットワーク上を流れるデータが 33% 増えます。保存された値を手作業で確認するには、Base64 を SELECT して Base64 からファイルへの変換 か Base64 から 16進数 で開いてください。

よくある質問

MySQL の FROM_BASE64 が NULL を返すのはなぜですか?

MySQL は不正な入力に対してエラーではなく NULL を返します。原因は、パディングの不足、URLセーフの - や _、ゴミ文字などです。Base64 バリデーター で入力を確認し、URLセーフな文字列はデコード前に REPLACE で直してください。

MySQL の TO_BASE64 の出力に改行が含まれるのはなぜですか?

TO_BASE64 は MIME の慣例に従い、76 文字ごとに改行を挿入します。1 行で出力するには 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 のサイズ増加 をご覧ください。

続けて読む