22.3. 字符集支持

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

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

22.3.1. 支持的字符集

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

Table 22-1. PostgreSQL字符集

名字 描述 语言 服务端? 字节数/字符 别名
BIG5 大五码 繁体中文 No 1-2 WIN950, Windows950
EUC_CN 扩展UNIX代码-CN 简体中文 Yes 1-3
EUC_JP 扩展UNIX代码-JP 日文 Yes 1-3
EUC_JIS_2004 扩展UNIX代码-JP, JIS X 0213 日文 Yes 1-3
EUC_KR 扩展UNIX代码-KR 韩文 Yes 1-3
EUC_TW 扩展UNIX代码-TW 繁体中文,台湾 Yes 1-3
GB18030 国标码 中文 No 1-2
GBK 扩展国标码 简体中文 No 1-2 WIN936, Windows936
ISO_8859_5 ISO 8859-5, ECMA 113 拉丁/西里尔语 Yes 1
ISO_8859_6 ISO 8859-6, ECMA 114 拉丁/阿拉伯语 Yes 1
ISO_8859_7 ISO 8859-7, ECMA 118 拉丁/希腊语 Yes 1
ISO_8859_8 ISO 8859-8, ECMA 121 拉丁/希伯莱语 Yes 1
JOHAB JOHAB 韩语 No 1-3
KOI8R KOI8-R 西里尔语(俄国) Yes 1 KOI8
KOI8U KOI8-U 西里尔语(乌克兰) Yes 1
LATIN1 ISO 8859-1, ECMA 94 西欧语 Yes 1 ISO88591
LATIN2 ISO 8859-2, ECMA 94 中欧语 Yes 1 ISO88592
LATIN3 ISO 8859-3, ECMA 94 南欧语 Yes 1 ISO88593
LATIN4 ISO 8859-4, ECMA 94 北欧语 Yes 1 ISO88594
LATIN5 ISO 8859-9, ECMA 128 土耳其语 Yes 1 ISO88599
LATIN6 ISO 8859-10, ECMA 144 日耳曼语 Yes 1 ISO885910
LATIN7 ISO 8859-13 波罗的海语 Yes 1 ISO885913
LATIN8 ISO 8859-14 凯尔特语 Yes 1 ISO885914
LATIN9 ISO 8859-15 带有欧洲语系和语调的LATIN1 Yes 1 ISO885915
LATIN10 ISO 8859-16, ASRO SR 14111 罗马尼亚语 Yes 1 ISO885916
MULE_INTERNAL Mule internal code 多语种Emacs Yes 1-4
SJIS Shift JIS 日语 No 1-2 Mskanji, ShiftJIS, WIN932, Windows932
SHIFT_JIS_2004 Shift JIS, JIS X 0213 日语 No 1-2
SQL_ASCII unspecified (see text) 任意 Yes 1
UHC Unified Hangul Code 韩语 No 1-2 WIN949, Windows949
UTF8 Unicode, 8-bit 全部 Yes 1-4 Unicode
WIN866 Windows CP866 西里尔语 Yes 1 ALT
WIN874 Windows CP874 泰国语 Yes 1
WIN1250 Windows CP1250 中欧语 Yes 1
WIN1251 Windows CP1251 西里尔语 Yes 1 WIN
WIN1252 Windows CP1252 西欧语 Yes 1
WIN1253 Windows CP1253 希腊语 Yes 1
WIN1254 Windows CP1254 土耳其语 Yes 1
WIN1255 Windows CP1255 希伯来语 Yes 1
WIN1256 Windows CP1256 阿拉伯语 Yes 1
WIN1257 Windows CP1257 波罗的语 Yes 1
WIN1258 Windows CP1258 越南语 Yes 1 ABC, 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数据库。当拷贝任何其他数据库时, 来自源数据库的编码和区域设置不能被改变,因为可能导致数据损坏。参阅Section 21.3 获取更多信息。

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

$ <kbd class="literal">psql -l</kbd>
                                         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)

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

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

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

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

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

服务器字符集 可用客户端字符集
BIG5 不支持做服务器端编码
EUC_CN EUC_CN, MULE_INTERNAL, UTF8
EUC_JP EUC_JP, MULE_INTERNAL, SJIS, UTF8
EUC_KR EUC_KR, MULE_INTERNAL, UTF8
EUC_TW EUC_TW, BIG5, MULE_INTERNAL, UTF8
GB18030 不支持做服务器端编码
GBK 不支持做服务器端编码
ISO_8859_5 ISO_8859_5, KOI8R, MULE_INTERNAL, UTF8, WIN866, WIN1251
ISO_8859_6 ISO_8859_6, UTF8
ISO_8859_7 ISO_8859_7, UTF8
ISO_8859_8 ISO_8859_8, UTF8
JOHAB JOHAB, UTF8
KOI8R KOI8R, ISO_8859_5, MULE_INTERNAL, UTF8, WIN866, WIN1251
KOI8U KOI8U, UTF8
LATIN1 LATIN1, MULE_INTERNAL, UTF8
LATIN2 LATIN2, MULE_INTERNAL, UTF8, WIN1250
LATIN3 LATIN3, MULE_INTERNAL, UTF8
LATIN4 LATIN4, MULE_INTERNAL, UTF8
LATIN5 LATIN5, UTF8
LATIN6 LATIN6, UTF8
LATIN7 LATIN7, UTF8
LATIN8 LATIN8, UTF8
LATIN9 LATIN9, UTF8
LATIN10 LATIN10, UTF8
MULE_INTERNAL MULE_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 所有支持的编码
WIN866 WIN866, ISO_8859_5, KOI8R, MULE_INTERNAL, UTF8, WIN1251
WIN874 WIN874, UTF8
WIN1250 WIN1250, LATIN2, MULE_INTERNAL, UTF8
WIN1251 WIN1251, ISO_8859_5, KOI8R, MULE_INTERNAL, UTF8, WIN866
WIN1252 WIN1252, UTF8
WIN1253 WIN1253, UTF8
WIN1254 WIN1254, UTF8
WIN1255 WIN1255, UTF8
WIN1256 WIN1256, UTF8
WIN1257 WIN1257, UTF8
WIN1258 WIN1258, UTF8

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

  • 用psql里的\encoding命令。 \encoding允许你动态修改客户端编码。 比如,把编码改变为SJIS,键入:

    \encoding SJIS
    
  • 使用libpq (Section 31.10)函数控制客户端编码。

  • 使用SET client_encoding TO。使用下面的SQL命令设置客户端编码:

    SET CLIENT_ENCODING TO '_value_';
    

    你也可以使用标准的SQL语法SET NAMES达到这个目的:

    SET NAMES '_value_';
    

    查询当前客户端编码:

    SHOW client_encoding;
    

    返回缺省编码:

    RESET client_encoding;
    
  • 使用PGCLIENTENCODING。如果在客户端的环境里定义了 PGCLIENTENCODING环境变量,那么在与服务器进行连接时将自动选择这个客户端编码。 这个编码随后可以用上面谈到的任何其它方法覆盖。

  • 使用client_encoding配置变量。 如果在client_encoding里设置了该变量, 那么在与服务器建立了连接之后,将自动选定这个客户端编码。 这个设置随后可以被上面提到的其它方法覆盖。

假如无法进行特定的字符转换— 比如, 你选的服务器编码是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的详细说明。

http://www.unicode.org/

Unicode主页。

RFC 3629

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