データがLatin1にあるPostgresqlデータベースがあります。一部の列からデータを選択すると、次のようなものが表示されるため、誰かがUTF8エンコードされたデータをロードしたようです。
SELECT symptoms from client
- -
"huvudvärke"
- -
ここで、「ä」は「ä」である必要があります。私はそれを置換で処理することができました、すなわち:
UPDATE client SET symptoms=replace(symptoms, 'ä', 'ä');
convert
やconvert_to
を使用するなど、いくつかの解決策を試しましたが、データは"huvudv\303\244rke"
のように見えます。
私の問題に対する既存の解決策はありますか?
編集:
SELECT symptoms, symptoms::bytea from client
- -
"huvudvärke";"huvudv\303\203\302\244rke"
- -
上記のUPDATEの後、symptoms :: byteaの出力でクエリを実行します。
SELECT symptoms, symptoms::bytea from client
- -
"huvudvärke";"huvudv\303\244rke"
- -
EDIT2:
select version();
"PostgreSQL 9.2.9, compiled by Visual C++ build 1600, 64-bit"
show client_encoding; --I'm using pgAdmin III 1.18.1
"UNICODE"
show server_encoding;
"UTF8"
SELECT symptoms, convert(convert_to(symptoms, 'utf-8'), 'latin-1', 'utf-8')::text from client;
"huvudvärke","huvudv\303\203\302\203\303\202\302\244rke"
使用しているクライアントがテキストエンコーディングについて混乱しているようです。おそらくラテン-1のようにutf-8バイトを送信しています。
小切手:
SHOW client_encoding;
SHOW server_encoding;
locale
を使用している場合は、ターミナルでpsql
コマンドあなたのupdate
は8進バイト\303\244
を "ä"のutf-8エンコーディングに置き換えています(U + 00E4)。自分が思っている場所で、latin-1でエンコードされたデータを置き換えているわけではありません。
観察する:
regress=> SELECT convert_from(BYTEA 'huvudv\303\244rke', 'latin-1');
convert_from
--------------
huvudvärke
(1 row)
regress=> SELECT convert_from(BYTEA 'huvudv\303\244rke', 'utf-8');
convert_from
--------------
huvudvärke
(1 row)
それだけでなく、replace
が最初に一致したのは、置換ターゲットがtf-8エンコード済みä
のバイトシーケンスであり、latin-1として解釈された場合のみです。 、つまり\303\203\302\244
。
Pgのバージョン、使用しているクライアントなどの詳細がないと、より具体的に特定することは困難ですが、根本的な原因は、クライアントがI/Oのエンコーディングでまったく問題を抱えていることです。
元のテキストは完全に破損しているため、UTF-8またはlatin-1では無効です。誰かがいくつかのUTF-8データを取得し、それをlatin-1としてデコードしてから、もう一度utf-8としてエンコードしたようです。
うん、確かに:
regress=> SELECT convert(convert_to('huvudvärke', 'utf-8'), 'latin-1', 'utf-8');
convert
---------------------------
huvudv\303\203\302\244rke
(1 row)
あなたの説明があります。
おそらく、すでにDBに誤ってエンコードされたデータの束がたくさんあると思いますが、このデータに気づかれたのはtwiceであるためです。あなたはおそらく日常的にutf-8バイトをlatin-1でエンコードされたフィールドに詰め込むようなことをしていますが、通常はそれらをutf-8として再びデコードするのでそれを回避します-そして今度は何か違うことをしました。
マングルされたテキストを元のテキストに戻したい場合は、間違ったエンコードプロセスを元に戻すだけです。 utf-8をデコードし、latin-1を出力してから、latf-1をutf-8として再インタペットして、もう一度デコードします。例:
regress=> SELECT convert_from(convert(BYTEA 'huvudv\303\203\302\244rke', 'utf-8', 'latin-1'), 'utf-8');
convert_from
--------------
huvudvärke
(1 row)
文字列をdest_encodingに変換します。元のエンコーディングはsrc_encodingで指定されます。文字列はこのエンコーディングで有効でなければなりません。変換はCREATE CONVERSIONで定義できます。また、いくつかの定義済みの変換があります。使用可能な変換については、表9-7を参照してください。
参照 その他の文字列関数
convert(string bytea, src_encoding name, dest_encoding name)
convert_to(text_in_database,'LATIN1')