问题报告 纠错本页面

22.3. 字符集支持

PostgreSQL中的字符集支持可以让你以各种字符集存储文本(也称为编码), 包含单字节字符集,比如ISO-8859系列和多字节字符集比如EUC(扩展Unix编码)、 UTF-8、Mule国际编码。 所有字符集都可以被客户端透明地使用。 但是有一些不支持在服务器上使用(即作为服务器端编码)。 缺省的字符集是在使用initdb初始化数据库集群的时候选择的。 在你创建数据库的时候是可以覆盖这个缺省值的。因此,你可以有多个数据库, 每个都有不同的字符集。

但是,有一个重要的限制,每个数据库的字符集必须与该数据库的LC_CTYPE(字符类别)以及 LC_COLLATE(字符串排序顺序)区域设置相兼容。对于C或者 POSIX区域,允许任何字符集, 但对于其他区域只有一个字符集设置能正常工作。(不过在Windows上,UTF-8编码可用于任何区域)。

22.3.1. 支持的字符集

表 22-1显示了可以在PostgreSQL中使用的 字符集。

表 22-1. PostgreSQL字符集

名字描述语言服务端?字节数/字符别名
BIG5大五码繁体中文No1-2WIN950, Windows950
EUC_CN扩展UNIX代码-CN简体中文Yes1-3 
EUC_JP扩展UNIX代码-JP日文Yes1-3 
EUC_JIS_2004扩展UNIX代码-JP, JIS X 0213日文Yes1-3 
EUC_KR扩展UNIX代码-KR韩文Yes1-3 
EUC_TW扩展UNIX代码-TW繁体中文,台湾Yes1-3 
GB18030国标码中文No1-2 
GBK扩展国标码简体中文No1-2WIN936, Windows936
ISO_8859_5ISO 8859-5, ECMA 113拉丁/西里尔语Yes1 
ISO_8859_6ISO 8859-6, ECMA 114拉丁/阿拉伯语Yes1 
ISO_8859_7ISO 8859-7, ECMA 118拉丁/希腊语Yes1 
ISO_8859_8ISO 8859-8, ECMA 121拉丁/希伯莱语Yes1 
JOHABJOHAB韩语No1-3 
KOI8RKOI8-R西里尔语(俄国)Yes1KOI8
KOI8UKOI8-U西里尔语(乌克兰)Yes1 
LATIN1ISO 8859-1, ECMA 94西欧语Yes1ISO88591
LATIN2ISO 8859-2, ECMA 94中欧语Yes1ISO88592
LATIN3ISO 8859-3, ECMA 94南欧语Yes1ISO88593
LATIN4ISO 8859-4, ECMA 94北欧语Yes1ISO88594
LATIN5ISO 8859-9, ECMA 128土耳其语Yes1ISO88599
LATIN6ISO 8859-10, ECMA 144日耳曼语Yes1ISO885910
LATIN7ISO 8859-13波罗的海语Yes1ISO885913
LATIN8ISO 8859-14凯尔特语Yes1ISO885914
LATIN9ISO 8859-15带有欧洲语系和语调的LATIN1Yes1ISO885915
LATIN10ISO 8859-16, ASRO SR 14111罗马尼亚语Yes1ISO885916
MULE_INTERNALMule internal code多语种EmacsYes1-4 
SJISShift JIS日语No1-2Mskanji, ShiftJIS, WIN932, Windows932
SHIFT_JIS_2004Shift JIS, JIS X 0213日语No1-2 
SQL_ASCIIunspecified (see text)任意Yes1 
UHCUnified Hangul Code韩语No1-2WIN949, Windows949
UTF8Unicode, 8-bit全部Yes1-4Unicode
WIN866Windows CP866西里尔语Yes1ALT
WIN874Windows CP874泰国语Yes1 
WIN1250Windows CP1250中欧语Yes1 
WIN1251Windows CP1251西里尔语Yes1WIN
WIN1252Windows CP1252西欧语Yes1 
WIN1253Windows CP1253希腊语Yes1 
WIN1254Windows CP1254土耳其语Yes1 
WIN1255Windows CP1255希伯来语Yes1 
WIN1256Windows CP1256阿拉伯语Yes1 
WIN1257Windows CP1257波罗的语Yes1 
WIN1258Windows CP1258越南语Yes1ABC, TCVN, TCVN5712, VSCII

并非所有API都支持上面列出的编码。比如, PostgreSQL JDBC驱动就不支持MULE_INTERNAL, LATIN6, LATIN8LATIN10

SQL_ASCII设置与其它设置表现得相当不同。如果服务器字符集是SQL_ASCII, 服务器根据ASCII标准解析0-127的字节值,而字节值为128-255的则当作未解析的字符。 如果设置为SQL_ASCII就不会有编码转换。因此,这个设置基本不用来声明所使用的编码, 因为这个声明会忽略编码。在大多数情况下,如果你使用了任何非ASCII数据, 那么使用SQL_ASCII设置都是不明智的,因为PostgreSQL 会无法帮助你转换或者校验非ASCII字符。

22.3.2. 设置字符集

initdb为一个PostgreSQL 集群定义缺省的字符集(编码),比如:

initdb -E EUC_JP

把缺省字符集设置为EUC_JP(用于日文的扩展Unix编码)。 如果你喜欢用长选项声明的话,可以用--encoding代替-E选项。 如果没有给出-E或者--encoding选项, initdb将基于指定的或者缺省的区域试图判断合适的编码。

你可以在数据库创建时指定非缺省编码,但是指定的编码必须与所选的区域相兼容:

createdb -E EUC_KR -T template0 --lc-collate=ko_KR.euckr --lc-ctype=ko_KR.euckr korean

将创建一个使用EUC_KR字符集以及ko_KR区域的 名字叫korean的数据库。另外一种实现方法是使用SQL命令:

CREATE DATABASE korean WITH ENCODING 'EUC_KR' LC_COLLATE='ko_KR.euckr' LC_CTYPE='ko_KR.euckr' TEMPLATE=template0;

注意上述命令声明拷贝template0数据库。当拷贝任何其他数据库时, 来自源数据库的编码和区域设置不能被改变,因为可能导致数据损坏。参阅第 21.3 节 获取更多信息。

数据库的编码是存储在pg_database系统表中的。 你可以用psql-l选项或\l 命令列出这些编码。

$ psql -l
                                         List of databases
   Name    |  Owner   | Encoding  |  Collation  |    Ctype    |          Access Privileges          
-----------+----------+-----------+-------------+-------------+-------------------------------------
 clocaledb | hlinnaka | SQL_ASCII | C           | C           | 
 englishdb | hlinnaka | UTF8      | en_GB.UTF8  | en_GB.UTF8  | 
 japanese  | hlinnaka | UTF8      | ja_JP.UTF8  | ja_JP.UTF8  | 
 korean    | hlinnaka | EUC_KR    | ko_KR.euckr | ko_KR.euckr | 
 postgres  | hlinnaka | UTF8      | fi_FI.UTF8  | fi_FI.UTF8  | 
 template0 | hlinnaka | UTF8      | fi_FI.UTF8  | fi_FI.UTF8  | {=c/hlinnaka,hlinnaka=CTc/hlinnaka}
 template1 | hlinnaka | UTF8      | fi_FI.UTF8  | fi_FI.UTF8  | {=c/hlinnaka,hlinnaka=CTc/hlinnaka}
(7 rows)

重要: 在大多数现代操作系统中,PostgreSQL可以通过 LC_CTYPE的设置决定使用哪种字符集,并且强制只使用匹配的数据库编码。在旧的操作系统上 你有责任确保使用所选区域所期望的编码。 如果这上面犯错误很可能导致与区域相关的操作表现出古怪的行为,比如排序。

即使当LC_CTYPE不是C或者POSIX时, PostgreSQL也允许超级用户创建 使用SQL_ASCII编码的数据库。正如 以上所述,SQL_ASCII不强制存储在数据库中的数据 具有任何特定的编码,所以这个选择带来 区域相关的不当行为的风险。使用这样的设置组合是不推荐的,也许有一天会被完全禁止。

22.3.3. 服务器和客户端之间的自动字符集转换

PostgreSQL支持在服务器和前端之间的自动编码转换。 转换信息在系统表pg_conversion中存储。 PostgreSQL带着一些预定义的转换。 它们在表 22-2中列出。 你可以使用SQL命令CREATE CONVERSION创建一个新的转换。

表 22-2. 客户/服务器字符集转换

服务器字符集可用客户端字符集
BIG5不支持做服务器端编码
EUC_CNEUC_CN, MULE_INTERNAL, UTF8
EUC_JPEUC_JP, MULE_INTERNAL, SJIS, UTF8
EUC_KREUC_KR, MULE_INTERNAL, UTF8
EUC_TWEUC_TW, BIG5, MULE_INTERNAL, UTF8
GB18030不支持做服务器端编码
GBK不支持做服务器端编码
ISO_8859_5ISO_8859_5, KOI8R, MULE_INTERNAL, UTF8, WIN866, WIN1251
ISO_8859_6ISO_8859_6, UTF8
ISO_8859_7ISO_8859_7, UTF8
ISO_8859_8ISO_8859_8, UTF8
JOHABJOHAB, UTF8
KOI8RKOI8R, ISO_8859_5, MULE_INTERNAL, UTF8, WIN866, WIN1251
KOI8UKOI8U, UTF8
LATIN1LATIN1, MULE_INTERNAL, UTF8
LATIN2LATIN2, MULE_INTERNAL, UTF8, WIN1250
LATIN3LATIN3, MULE_INTERNAL, UTF8
LATIN4LATIN4, MULE_INTERNAL, UTF8
LATIN5LATIN5, UTF8
LATIN6LATIN6, UTF8
LATIN7LATIN7, UTF8
LATIN8LATIN8, UTF8
LATIN9LATIN9, UTF8
LATIN10LATIN10, UTF8
MULE_INTERNALMULE_INTERNAL, BIG5, EUC_CN, EUC_JP, EUC_KR, EUC_TW, ISO_8859_5, KOI8R, LATIN1 to LATIN4, SJIS, WIN866, WIN1250, WIN1251
SJIS不支持做服务器端编码
SQL_ASCII任意(不会发生编码转换)
UHC不支持做服务器端编码
UTF8所有支持的编码
WIN866WIN866, ISO_8859_5, KOI8R, MULE_INTERNAL, UTF8, WIN1251
WIN874WIN874, UTF8
WIN1250WIN1250, LATIN2, MULE_INTERNAL, UTF8
WIN1251WIN1251, ISO_8859_5, KOI8R, MULE_INTERNAL, UTF8, WIN866
WIN1252WIN1252, UTF8
WIN1253WIN1253, UTF8
WIN1254WIN1254, UTF8
WIN1255WIN1255, UTF8
WIN1256WIN1256, UTF8
WIN1257WIN1257, UTF8
WIN1258WIN1258, UTF8

要想打开自动字符集转换功能,你必须告诉PostgreSQL 你想在客户端使用的字符集(编码)。 你可以用好几种方法实现这个目的。

假如无法进行特定的字符转换— 比如, 你选的服务器编码是EUC_JP而客户端是LATIN1, 那么有些返回的日文字符不能转换成LATIN1 —这时将报告错误。

如果客户端字符集定义成了SQL_ASCII, 那么编码转换会被关闭,不管服务器的字符集是什么都一样。 和服务器一样,除非你的工作环境全部是ASCII数据,否则使用SQL_ASCII是不明智的。

22.3.4. 进一步阅读

下面是学习各种类型的编码系统的好地方。

CJKV Information Processing: Chinese, Japanese, Korean & Vietnamese Computing

包含EUC_JP, EUC_CN, EUC_KR, EUC_TW的详细说明。

https://www.unicode.org/

Unicode主页。

RFC 3629

UTF-8 (8-bit UCS/Unicode转换格式)的定义。