web-dev-qa-db-ja.com

Postgresでの文字エンコーディング

PostgresにUTF8データが保存されています。 Perlスクリプトを使用してクエリを実行し、適切に表示できます。 Postgresクライアントを使用すると、エンコードがオフのように表示されます。\u0087\u0081のような文字が表示されます。

データベース内から:

=> \encoding
UTF8

シェルで(修正の可能性がある他の場所で読んだので、手動でLANGUAGEを設定しました。):

$locale
LANG=en_US.UTF-8
LANGUAGE=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

これはUbuntu 16.04にあります。

どの設定を見逃しましたか?

Psqlを生成するコードを追加するために編集:

#!/usr/bin/Perl

use strict;
use warnings;
use DBI;

### Source DB setup
my $maria_database="srcdb";
my $maria_user = "";
my $maria_password = "";
my $maria_Host= "localhost";

my $mariadbh = DBI->connect("dbi:mysql:database=$maria_database;Host=$maria_Host","$maria_user","$maria_password",{AutoCommit=>1,RaiseError=>1,PrintError=>0,mysql_enable_utf8=>1});

my $mysrcquery = "SELECT fields from sourcetable limit 2;";
my $src = $mariadbh->prepare($mysrcquery);

### Destination DB setup
my $postgresql_database="desdb";
my $postgresql_user="";
my $postgresql_password="";
my $postgresql_Host="localhost";

my $dbh = DBI->connect("DBI:Pg:dbname=$postgresql_database; Host=$postgresql_Host", "$postgresql_user", "$postgresql_password", {AutoCommit => 0,pg_enable_utf8 => 1});

my $pginsertquery = "insert into desttable (fields) VALUES (?)";
my $pginsert = $dbh->prepare($pginsertquery);

$src->execute();
my ($col0);
$src->bind_columns(undef, \$col0 );

### Loop through results and insert in to psql
while($src->fetch())
{
  print $col0;
  $pginsert->execute($col0);
}

$dbh->commit;
$dbh-> disconnect or warn "Disconnection failed: DBI::errstr\n";
$mariadbh-> disconnect or warn "Disconnection failed: DBI::errstr\n";

Sqldumpをテストします。

--
-- PostgreSQL database dump
--

-- Dumped from database version 9.6.1
-- Dumped by pg_dump version 9.6.1

SET statement_timeout = 0;
SET lock_timeout = 0;
SET idle_in_transaction_session_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET row_security = off;

SET search_path = public, pg_catalog;

SET default_tablespace = '';

SET default_with_oids = false;

--
-- Name: test; Type: TABLE; Schema: public; Owner: testuser
--

CREATE TABLE test (
    testdata text
);


ALTER TABLE test OWNER TO testuser;

--
-- Name: test id; Type: DEFAULT; Schema: public; Owner: testuser
--

ALTER TABLE ONLY test ALTER COLUMN id SET DEFAULT nextval('test_id_seq'::regclass);


--
-- Data for Name: test; Type: TABLE DATA; Schema: public; Owner: testuser
--

COPY test (testdata) FROM stdin;
пÑ<80>ивеÑ<82>Ñ<81>Ñ<82>вÑ<83>Ñ<8e>
\.


--
-- PostgreSQL database dump complete
--
2
thatguy

\u0087END OF SELECTED AREA )および\u0081は、LATIN-1ブロックの制御文字です。それらを\u0087\u0081として表示することは実際には慣習であり、端末が行っていることのようです。

データベースにデータを挿入するためのPerlスクリプトを見せていただけますか? Perlでのutf8の操作はPITAであるため、Perlはutf8以外のデータを挿入していると私は想定しています。 PostgreSQLはそれがutf8であることを想定しており、ターミナルはそれを表示する方法を知らない。

  • 実際にはutf8ではなく、utf8としてマークアップされています。
  • または、utf8でエンコードされた正当な制御文字があります。

元のフォーマットからデコードせずにフラグを設定するutf8::upgradeなどを使用した場合は注意してください。

助言

DBD :: Pg、DBD :: mysqlを更新する

最初にDBD :: PgとDBD :: mysqlの両方を更新します

cpan DBD::Pg DBD::mysql 

DBD :: mysqlのバグ

変更ログを確認すると、DBD :: mysqlには常にバグがあり、開発バージョン( DBD-mysql-4.041_01 )をインストールすることもできます。

2016-12-12 Patrick Galbraith, Michiel Beijen, DBI/DBD community (4.041_1)
* Unicode fixes: when using mysql_enable_utf8 or mysql_enable_utf8mb4,
  previous versions of DBD::mysql did not properly encode input statements
  to UTF-8 and retrieved columns were always UTF-8 decoded regardless of the
  column charset.
  Fix by Pali Rohár.
  Reported and feedback on fix by Marc Lehmann
  (https://rt.cpan.org/Public/Bug/Display.html?id=87428)
  Also, the UTF-8 flag was not set for decoded data:
  (https://rt.cpan.org/Public/Bug/Display.html?id=53130)

彼らが地獄で何をしているのか誰が知っている。 Unicodeは複雑で、MySQLの開発者とユーザーが理解していないことは驚くに値しません。

仮定の解除

pg_enable_utf8mysql_enable_utf8の設定を解除します。これらのオプションが存在するふりをします。内部変数にutf8フラグを強制的に設定しています。あなたはおそらくそれをしたくないでしょう。すべてがutf8であることを確認できないか、正しく機能していることは明らかです。仮定を削除する時間。より多くの仮定を作成しません。

サンプルケースが必要です。外字がUnicodeエスケープシーケンスとして表示されていると主張していますが、表示できないのは制御文字のみです。おそらく、この全体を単純にして、テーブルpg_dump -t <Table>をダンプするか、問題のある行を一時テーブルにコピーしてダンプすることができます。次に、そのデータを確認して、取得した内容を確認できます。

1
Evan Carroll