はじめに
この記事はタイトルの通り、Windows環境でpsqlコマンドを使ってSQLファイルを実行する際に起きたエンコードのエラーと解決策を紹介します。
今までだったらPgAdminでファイルを実行すれば事足りる話だったと思います。ただ、pdAdmin4の動作が不安定ということもあり、筆者のように導入を諦めてしまった方もいると思います。そんな人に読んでいただければと思います。
前提
環境
- Windows Server 2012
- PowerShell 4.0
- PostgreSQL 10.4
DBの設定
名前 | エンコーディング | 照合順序 | Ctype |
---|---|---|---|
sample | UTF8 | C | C |
用意したファイル
UTF-8形式で保存しました。
create table category(
id int not null,
name varchar(100) not null,
primary key(id)
);
comment on table category is 'カテゴリ';
comment on column category.id is 'ID';
comment on column category.name is '名前';
起きた問題
コマンドpsql -U postgres -d sample -f create_category.sql
をPowerShellで実行しましたが以下のエラーが発生しました。
PS C:\Users\Administrator > psql -U postgres -d sample -f create_category.sql
CREATE_TABLE
psql:create_category.sql:6: ERROR: character with byte sequence 0x86 in encoding "SJIS" has no equivalent in encoding "UTF8"
Tableは作成できましたが、日本語のコメントが書いてある部分でエラーになっています。
なぜかUTF-8形式のファイルなのにPostgreSQLがSJIS形式で読み込もうとしていますね。
諸悪の根源
client_encodingの文字コードがSJISになっているので、失敗したみたいです。
SHOW client_encoding;
client_encoding
--------------------
SJIS
対策
対策1.ファイルをSJIS形式で保存してから実行する
create_category.sqlをSJIS形式に変換してcreate_category_sjis.sqlとして保存しました。中身は同じ。
PS C:\Users\Administrator > psql -U postgres -d sample -f create_category_sjis.sql
CREATE_TABLE
COMMENT
COMMENT
COMMENT
うん、大丈夫ですね。でもこれclient_encodingの設定に依存しているので、Linux環境で同じように実行したら、SJISファイルをUTF8で読んでエラーが起こりそう。
対策2.SQLファイルの先頭でclient_encodingを変更する
さっきのcreate_category.sql(UTF8)の先頭に\encoding UTF-8
と書き足します。
\encoding UTF8;
--以下は変更していない
create table category(
id int not null,
name varchar(100) not null,
primary key(id)
);
comment on table category is 'カテゴリ';
comment on column category.id is 'ID';
comment on column category.name is '名前';
結果は以下の通り
PS C:\Users\Administrator > psql -U postgres -d sample -f create_category.sql
CREATE_TABLE
COMMENT
COMMENT
COMMENT
UTF8で読み込めたね、よくできましたね!
しかしSQLファイル冒頭に\encoding UTF8
と毎回書くのは少し煩わしいです。
対策3.Windowsの環境変数でclient_encodingを書き換える
※@c-yanさん、@dany1468さんのコメントより追記
PS C:\Users\Administrator> $env:PGCLIENTENCODING = "UTF8"
PostgreSQLでclient_encodingを確認すると、UTF-8になっていることが分かります。
postgres=# \encoding
UTF-8
ただ、副作用でテーブル内の日本語のデータが文字化けする場合があります。
PowerShellのエンコード形式がデフォルトではUTF-8ではないからです。
こちらについてはSQLファイルの実行と直接関係ないので説明は割愛させていただきます。
以下のサイトにPowerShellのエンコード形式とフォントの変更方法が書いてありますので
それを参考に対策してください。
https://qiita.com/yufu/items/86a455f948a3e1c0ef97
補足
本当はSQLファイル内にエンコード形式を書くのではなく、実行するコマンド内で指定したかったのですが、分からなかったので上記の方法を使いました。もっと良い方法、コマンドでエンコード形式を指定する方法をご存知の方がいたら教えていただけると嬉しいです。