22.2. 字符集支持

PostgreSQL 能够以各种字符集存储文本, 比如 ISO-8859 系列和EUC(扩展 Unix 编码)、UTF-8 、Mule 国际编码。 所有字符集都可以在服务器上透明地使用。 如果你使用了来自其它数据源的扩展函数, 那么它取决于他们是否正确地书写了代码。 缺省的字符集是在使用 initdb 初始化数据库集群的时候选择的。 在你创建数据库的时候是可以覆盖这个缺省的。 因此,你可以有多个数据库,每个都有不同的字符集。

An important restriction, however, is that each database's character set must be compatible with the database's LC_CTYPE (character classification) and LC_COLLATE (string sort order) locale settings. For C or POSIX locale, any character set is allowed, but for other locales there is only one character set that will work correctly. (On Windows, however, UTF-8 encoding can be used with any locale.)

一项重要的限制是每个数据库的字节设置必须被数据库的LC_CTYPE(字节分类)和 LC_COLLATE(字符串存储命令)区域设置兼容。 对于C或者POSIX区域,任何字符设置都是被允许的,但是对于其它区域仅仅只可以设置一种字符才可以正常工作。 (在windows操作系统,UTF-8编码可以在任何一个区域使用。)

22.2.1. 支持的字符集编码

Table 22-1 显示了可以用在 PostgreSQL上的编码。

Table 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_INTERNAL国际编码多语种 EmacsYes1-4 
SJISShift JIS日语No1-2Mskanji, ShiftJIS, WIN932, Windows932
SHIFT_JIS_2004Shift JIS, JIS X 0213日语No1-2 
SQL_ASCII未声明(见文本)任意Yes1 
UHC统一韩语编码韩语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, LATIN8, and LATIN10

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

22.2.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

创建一个叫做korean的数据库,使用字集EUC_KR和区域ko_KR, 另外一种实现方法是使用 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列出这些编码.

$ 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)

Important: 在大多数现代的操作系统中,PostgreSQL可以决定 哪个字符集被LC_CTYPE设置,它会在匹配数据库编码时运行。 在比较老的操作系统上,你的任务是保证你用到的编码是你选择的区域所预期的。这个区域的 的一个错误可能会导致locale-dependent的错误行为。

PostgreSQL将会允许超级用户用SQL_ASCII编码创建数据库,即使 LC_CTYPE不是CPOSIX。就像上面注意到的, SQL_ASCII不执行那些在数据库里有特别编码的数据存储,这个选择构成locale-dependent发生错误行为的风险。 使用这些组合的设置已经过时,或者某一天可能被禁止。

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

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

Table 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 is unwise是不明智的。

22.2.4. 进一步阅读

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

http://www.i18ngurus.com/docs/984813247.htm

一整套有关字符集,编码以及代码页的文档。

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

详细地解释了第3.2节出现的 EUC_JP, EUC_CN, EUC_KR, EUC_TW编码。

http://www.unicode.org/

Unicode的主页。

RFC 3629

UTF-8 的定义