Postgres导入时错误地存储UTF-8值

时间:2014-09-24 15:07:42

标签: postgresql utf-8

On Postgres 9.1 我只将数据(无结构)导入到不包含记录的UTF-8数据库中

psql -l给了我

  Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-----------+----------+----------+-------------+-------------+-----------------------
 glyph     | glyph    | UTF8     | en_GB.UTF-8 | en_GB.UTF-8 | =Tc/glyph            +
           |          |          |             |             | glyph=CTc/glyph

表格如下:

-- Table: sign

-- DROP TABLE sign;

CREATE TABLE sign
(
  id serial NOT NULL,
  sign_ref character varying(150) NOT NULL,
  CONSTRAINT pk_sign PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE sign
  OWNER TO glyph;

-- Index: ix_sign_sign_ref

-- DROP INDEX ix_sign_sign_ref;

CREATE UNIQUE INDEX ix_sign_sign_ref
  ON sign
  USING btree
  (sign_ref COLLATE pg_catalog."default");

从我的SQL文件插入值:
命令:psql -h localhost -d glyph -U glyph -f import.sql

START TRANSACTION;
SET standard_conforming_strings=off;
SET escape_string_warning=off;
SET CONSTRAINTS ALL DEFERRED;
INSERT INTO "sign" VALUES (29585,'DE₂');
COMMIT;

但是,这已经在db中转换为“DE”。 我做错了什么?

编辑:

select convert_to(
(select sign_ref from sign where id = 29585), 'utf8'); 

给我:
DE\303\242\302\202\302\202

1 个答案:

答案 0 :(得分:3)

问题是输入(INSERT查询)在UTF-8中编码,但解释为LATIN1(或LATIN9),可能是因为client_encoding设置错误

推理线是:

  1. utf-8中DE₂的字节表示形式为44 45 e2 82 82(十六进制)
  2. 在LATIN1中解释时,这些字节表示DEâ和两个控制字符0x82。这是什么进入数据库。
  3. 当用正常的utf-8重新读取它时,得到的是â在utf-8中编码,接着是在utf-8中编码的两个U + 0082。以十六进制字节表示,即四进制,DE\303\242\302\202\302\202,这正是您convert_to(sign_ref, 'utf-8')所获得的。$ cat > test.sql create table test(t text); set client_encoding to latin1; -- intentional mistake for the purpose of demoing insert into test values('DE₂'); $ psql -d test -f test.sql $ psql -d test select * from test; t ----------------- DEâ\u0082\u0082 set bytea_output='escape'; select convert_to(t, 'utf-8') from test; convert_to ---------------------------- DE\303\242\302\202\302\202 。{{1}}。{{1}}。{{1}}。{{1}}。{{1}}
  4. 使用utf-8中的终端进行演示:

    {{1}}