TECH BLOG
技術ブログ

ARTICLE

  • 2024-04-20 PostgreSQL

    ERROR: invalid byte sequence for encoding の抑制方法

PostgreSQL はご存知のとおり日本語対応している(日本語でメッセージを表示したりできる)のですが、サーバ側とクライアント側でサポートされているエンコーディングが違います。
サーバ側でサポートされている日本語対応のエンコーディングは

  • EUC_JP
  • UTF-8

の 2 つとなります。

Windows 環境で主流となっている SJIS は、クライアント側しか対応しておらず、PostgreSQL のデータベースクラスタに SJIS でデータを格納することはできません。

ただし、クライアント側では SJIS もサポートされているため、Windows のコマンドプロンプトなどのエンコーディングが SJIS (cp932)の環境で psql を実行してもメッセージが文字化けすることはありません。

※PostgreSQL がサポートしているエンコーディングの詳細については、公式ドキュメントを参照してください。
【 PostgreSQL 文書 15.4 - 24.3. 文字セットサポート - 】
https://www.postgresql.jp/document/15/html/multibyte.html

ERROR: invalid byte sequence for encoding

クライアント側のエンコーディングが SJIS で、サーバ側のエンコーディングが UTF-8 の場合、PostgreSQL はデータの文字コードを自動的に変換してデータをやりとりします。
この変換が上手くいかない場合、「ERROR: invalid byte sequence for encoding」が発生する可能性があります。

具体的に発生させてみます

では、実際にこの「ERROR: invalid byte sequence for encoding」を発生させてみます。
まず test.sql という SQL ファイルを用意して SJIS で保存しておきます。
test.sql の内容は下記のようなものです。

test.sql
CREATE TABLE test_table (i INTEGER, val TEXT);
INSERT INTO test_table VALUES (1, 'テスト文字列');
SELECT * FROM test_table;

test_table テーブルを作成して、INSERT で 1 レコード追加して、test_table テーブルのデータを表示する、という簡単なものです。
これをエンコーディングが UTF-8 の端末で実行します。

$ psql -f test.sql 
CREATE TABLE
psql:test.sql:4: ERROR:  invalid byte sequence for encoding "UTF8": 0x83
 i | val 
---+-----
(0 rows)

上記の通り 「invalid byte sequence for encoding "UTF8": 0x83」が発生しました。
SQL ファイルとクライアント側のエンコーディングが一致していないため、エラーが発生しているということになります。

invalid byte sequence for encoding を抑制する方法

「invalid byte sequence for encoding」を抑制するには、SQL ファイルとクライアント側のエンコーディングを合わせればよく、上記の例ですと SQL ファイルのエンコーディングを SJIS から UTF-8 に変更すればエラーは発生しません。
ただ、本番運用の制約などで SQL ファイルのエンコーディングを変更できない場合には、クライアント側のエンコーディングを変更する必要があります。
具体的には PostgreSQL の client_encoding というパラメータを変更します。

client_encoding の設定方法はいくつかありますが、過去のブログ記事で紹介していますので、そちらを参照してください。

https://www.insight-ltd.co.jp/tech_blog/postgresql/pg-parameter/772/

簡単な方法としては、SQL ファイルの先頭に SET コマンドを記述することや、psql の -c オプションで SET コマンドを記述することです。
実際にやってみます。

postgres@server:~/work_dir/blog_mojibake$ psql -p 5416 -c "SET client_encoding = 'SJIS' " -f test.sql 
SET
CREATE TABLE
INSERT 0 1
 i |     val      
---+--------------
 1 | ?e?X?g??????
(1 row)

上記のとおり psql の -c オプションで SET client_encoding = 'SJIS' を実行することでエラーが発生することなくデータを追加できました。
プロンプトのエンコーディングが UTF8 なため文字化けしていますが、新たに接続しなおしてデータを確認すると、文字化けすることなく確認できます。

postgres=# SELECT * FROM test_table;
 i |     val      
---+--------------
 1 | テスト文字列
(1 row)

文字化けすることなく追加したデータを参照できました。

まとめ

簡単ではありますが、以上が「invalid byte sequence for encoding」エラーを抑制する方法の説明となります。
ポイントとしては、client_encoding パラメータとクライアント側のエンコーディングを合わせることになります。
どうしても「invalid byte sequence for encoding」エラーや文字化けが発生する処理がある場合については、その処理の直前で client_encoding パラメータがどうなっているのかを確認することで原因の切り分けを行えると思います。

CATEGORY

ARCHIVE

PostgreSQLの
ハイパフォーマンスチューニングのご相談は
株式会社インサイトまで
お気軽にお問い合わせください。

CONTACT