Postgres 数据库编码问题

Cyr*_*bil 5 postgresql utf-8 encoding

我正在努力从我的表中转换编码错误的数据。例如,我有一个字段,Nadège它应该是Nadège.

我尝试使用 Postgres 的函数convert, convert_fromconvert_to但没有取得多大成功。

db=# SHOW client_encoding;
 client_encoding 
-----------------
 UTF8
(1 row)

db=# SHOW server_encoding;
 server_encoding 
-----------------
 UTF8
(1 row)

db=# SELECT "firstName", encode("firstName"::bytea, 'hex') FROM contact;       
 firstName |       encode       
-----------+--------------------
 Nadège    | 4e6164c3a86765
 Nadège   | 4e6164c383c2a86765
(2 rows)

db=# SELECT "firstName", convert_from("firstName"::bytea, 'latin1') FROM contact WHERE "lastName" ILIKE 'crochard';
 firstName |  convert_from  
-----------+----------------
 Nadège    | Nadège
 Nadège   | NadÃ\u0083¨ge
(2 rows)

db=# SELECT "firstName", convert("firstName"::bytea, 'utf8', 'latin1') FROM contact;                                                                                                                                                       
 firstName |     convert      
-----------+------------------
 Nadège    | \x4e6164e86765
 Nadège   | \x4e6164c3a86765
(2 rows)
Run Code Online (Sandbox Code Playgroud)

使用 python 我能够获得正确的编码:

data.encode('latin1').decode('utf8')
Run Code Online (Sandbox Code Playgroud)

关于如何在 postgres 中转换这些错误编码的数据的任何提示?

Cra*_*ger 4

正如您所正确识别的,Nad\xc3\x83\xc2\xa8geUTF-8 表示是 Nad\xc3\xa8ge错误地解码为 ISO-8859-1(“latin-1”)。然后,根据您的情况,重新编码为 UTF-8 以存储在数据库中。

\n\n

要修复它,您需要:

\n\n
    \n
  • 获取当前表示并将 UTF-8 解码为 latin-1 作为字节字符串
  • \n
  • 重新解释字节字符串,将其解码为 utf-8
  • \n
\n\n

所以:

\n\n
test=> SELECT convert_from(convert_to(\'Nad\xc3\x83\xc2\xa8ge\', \'latin-1\'), \'utf-8\');\n convert_from \n--------------\n Nad\xc3\xa8ge\n(1 row)\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

Python 等效项将接近您编写的内容,但以 unicode 表示形式开始,以说明 PostgreSQL 将所有内容存储在数据库编码中。就像是:

\n\n
>>> print u"Nad\xc3\x83\xc2\xa8ge".encode("latin-1").decode("utf-8")\nNad\xc3\xa8ge\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

text您尝试的所有解决方案的问题是从到 的转换bytea 使用数据库编码。因此,您从 utf-8 错误解码为 latin-1 的 utf-8 表示形式的字节开始。对于演员阵容,你必须写:

\n\n
test=> SELECT convert_from(convert_to(convert_from((TEXT \'Nad\xc3\x83\xc2\xa8ge\')::bytea, \'utf-8\'), \'latin-1\'), \'utf-8\');\n convert_from \n--------------\n Nad\xc3\xa8ge\n(1 row)\n
Run Code Online (Sandbox Code Playgroud)\n\n

因为在重新解释为 latin-1 并再次解码之前,您必须显式解码由强制转换生成的 utf-8 表示形式。

\n\n

你只需要使用convert_to(mycol, \'latin-1\')而不是mycol::bytea

\n