ERROR: invalid byte sequence for encoding "SJIS": ...
きっかけは上記のようなエラー。 機種依存文字が影響していることは、すぐに分かりましたが、client側での対処に手こずった。
随分、久しぶりにpostgresを触ったせいですね。
参考url
https://www.postgresql.jp/document/9.6/html/multibyte.html
サーバ側(postgres)側の環境
今回の為、test DBをencoding=utf8で createdb しています。 ちなみにサーバ側のencodingに、sjisやcp932はないようです。
$ /usr/local/pgsql/bin/psql --version psql (PostgreSQL) 9.6.5 $ /usr/local/pgsql/bin/psql --username=postgres -l List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+----------+----------+-------------+-------------+----------------------- postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres test | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
$ /usr/local/pgsql/bin/psql --username=postgres test $ test=# CREATE TABLE test ( atri_id serial, /* = AUTO_INCREMENT of mysql */ atri_val varchar(20), PRIMARY KEY (atri_id) ); test=# \d List of relations Schema | Name | Type | Owner --------+------------------+----------+---------- public | test | table | postgres public | test_atri_id_seq | sequence | postgres (2 rows) test=# \d test Table "public.test" Column | Type | Modifiers ----------+-----------------------+-------------------------------------------------------- atri_id | integer | not null default nextval('test_atri_id_seq'::regclass) atri_val | character varying(20) | Indexes: "test_pkey" PRIMARY KEY, btree (atri_id)
クライアント側(perl)の環境変数に PGCLIENTENCODING = SJIS を設定
https://www.postgresql.jp/document/9.6/html/multibyte.html
上記のpostgresのdocumentにおいて、client側encodingの指定として 1)「SET CLIENT_ENCODING TO '~'」2)「SET NAMES '~'」3)「$ENV{PGCLIENTENCODING}」 があるように記載されていますが、 私の環境において1),2)は上手く動作せず、3)の$ENV{PGCLIENTENCODING}に落ち着きました。
#!/usr/local/bin/perl use utf8; use strict; use warnings; use DBI; use Encode; use Data::Dumper; my $DB_CONF = {db=>"DBI:Pg:dbname=test;host=localhost;", user=>'postgres', pass=>'', client_encoding => 'SJIS', option => {AutoCommit=>0, # pg_enable_utf8=>0, RaiseError => 1, PrintError => 0} }; main(); sub main { $ENV{PGCLIENTENCODING} = $DB_CONF->{client_encoding}; my $dbh = connect_db(); my $sql =<<EOF; insert into test (atri_val) values(?) EOF my $sth = $dbh->prepare($sql); my $org_val = '髙'; # my $new_val = Encode::encode('utf8',$org_val); my $new_val = Encode::encode('cp932',$org_val); unless( $sth->execute($new_val) ){ print STDERR $sth->errstr,"\n"; } $dbh->commit; $dbh->disconnect; } sub connect_db { my $dbh = DBI->connect($DB_CONF->{db}, $DB_CONF->{user}, $DB_CONF->{pass}, $DB_CONF->{option}); # $dbh->do("SET NAMES '$DB_CONF->{client_encoding}'") or # die "cannot set encoding $!"; # $dbh->do("SET CLIENT_ENCODING TO $DB_CONF->{client_encoding}") or # die "cannot set encoding $!"; return $dbh; }