23.3. 字符集支持

PostgreSQL 对字符集的支持使您可以将文本存储为多种字符集(也称为编码),包括单字节字符集(例如 ISO 8859 系列)和多字节字符集(例如 EUC(扩展 Unix 代码)), UTF-8 和 Mule 内部代码。Client 端可以透明地使用所有支持的字符集,但是不支持在服务器内部使用其中的一些字符集(即,作为服务器端编码)。使用initdb初始化 PostgreSQL 数据库集群时,将选择默认字符集。创建数据库时可以覆盖它,因此可以有多个数据库,每个数据库都有不同的字符集。

但是,一个重要的限制是每个数据库的字符集必须与数据库的LC_CTYPE(字符分类)和LC_COLLATE(字符串排序 Sequences)区域设置兼容。对于CPOSIX语言环境,允许使用任何字符集,但是对于其他 libc 提供的语言环境,只有一个字符集可以正常工作。 (但是,在 Windows 上,UTF-8 编码可以与任何语言环境一起使用.)如果配置了 ICU 支持,则 ICU 提供的语言环境可以与大多数(但不是全部)服务器端编码一起使用。

23 .3.1. 支持的字符集

Table 23.1显示了可在 PostgreSQL 中使用的字符集。

表 23.1 PostgreSQL 字符集

NameDescriptionLanguageServer?ICU?Bytes/CharAliases
BIG5Big FiveTraditional ChineseNoNo1-2WIN950 , Windows950
EUC_CN扩展 UNIX Code-CNSimplified ChineseYesYes1-3
EUC_JP扩展 UNIX Code-JPJapaneseYesYes1-3
EUC_JIS_2004扩展 UNIX Code-JP,JIS X 0213JapaneseYesNo1-3
EUC_KR扩展的 UNIX Code-KRKoreanYesYes1-3
EUC_TW扩展 UNIX 代码 TW繁体中文,台湾语YesYes1-3
GB18030National StandardChineseNoNo1-4
GBK扩展国家标准Simplified ChineseNoNo1-2WIN936 , Windows936
ISO_8859_5ISO 8859-5,ECMA 113Latin/CyrillicYesYes1
ISO_8859_6ISO 8859-6,ECMA 114Latin/ArabicYesYes1
ISO_8859_7ISO 8859-7,ECMA 118Latin/GreekYesYes1
ISO_8859_8ISO 8859-8,ECMA 121Latin/HebrewYesYes1
JOHABJOHABKorean (Hangul)NoNo1-3
KOI8RKOI8-RCyrillic (Russian)YesYes1KOI8
KOI8UKOI8-UCyrillic (Ukrainian)YesYes1
LATIN1ISO 8859-1,ECMA 94Western EuropeanYesYes1ISO88591
LATIN2ISO 8859-2,ECMA 94Central EuropeanYesYes1ISO88592
LATIN3ISO 8859-3,ECMA 94South EuropeanYesYes1ISO88593
LATIN4ISO 8859-4,ECMA 94North EuropeanYesYes1ISO88594
LATIN5ISO 8859-9,ECMA 128TurkishYesYes1ISO88599
LATIN6ISO 8859-10,ECMA 144NordicYesYes1ISO885910
LATIN7ISO 8859-13BalticYesYes1ISO885913
LATIN8ISO 8859-14CelticYesYes1ISO885914
LATIN9ISO 8859-15带有欧元和口音的 LATIN1YesYes1ISO885915
LATIN10ISO 8859-16,ASRO SR 14111RomanianYesNo1ISO885916
MULE_INTERNALule 子内部代码Multilingual EmacsYesNo1-4
SJISShift JISJapaneseNoNo1-2Mskanji , ShiftJIS , WIN932 , Windows932
SHIFT_JIS_2004Shift JIS,JIS X 0213JapaneseNoNo1-2
SQL_ASCII未指定(见 Literals)anyYesNo1
UHC统一韩文代码KoreanNoNo1-2WIN949 , Windows949
UTF8Unicode, 8-bitallYesYes1-4Unicode
WIN866Windows CP866CyrillicYesYes1ALT
WIN874Windows CP874ThaiYesNo1
WIN1250Windows CP1250Central EuropeanYesYes1
WIN1251Windows CP1251CyrillicYesYes1WIN
WIN1252Windows CP1252Western EuropeanYesYes1
WIN1253Windows CP1253GreekYesYes1
WIN1254Windows CP1254TurkishYesYes1
WIN1255Windows CP1255HebrewYesYes1
WIN1256Windows CP1256ArabicYesYes1
WIN1257Windows CP1257BalticYesYes1
WIN1258Windows CP1258VietnameseYesYes1ABC , TCVN , TCVN5712 , VSCII

并非所有的 Client 端 API 都支持所有列出的字符集。例如,PostgreSQL JDBC 驱动程序不支持MULE_INTERNALLATIN6LATIN8LATIN10

SQL_ASCII设置的行为与其他设置大不相同。当服务器字符集为SQL_ASCII时,服务器将根据 ASCII 标准解释字节值 0-127,而将字节值 128-255 视为未解释字符。设置为SQL_ASCII时将不进行编码转换。因此,此设置不是声明正在使用特定的编码,而是声明对编码的无知。在大多数情况下,如果要处理任何非 ASCII 数据,则使用SQL_ASCII设置是不明智的,因为 PostgreSQL 无法通过转换或验证非 ASCII 字符来帮助您。

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

这将创建一个名为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 22.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

在大多数现代 os 上,PostgreSQL 可以确定LC_CTYPE设置所隐含的字符集,并且它将强制要求仅使用匹配的数据库编码。在较旧的系统上,您有责任确保使用所选语言环境所期望的编码。该区域中的错误很可能导致诸如排序之类的与语言环境相关的操作的奇怪行为。

PostgreSQL 允许超级用户使用SQL_ASCII编码创建数据库,即使LC_CTYPE不是CPOSIX也不行。如上所述,SQL_ASCII并不强制数据库中存储的数据具有任何特定的编码,因此此选择带来了与语言环境相关的行为异常的风险。不建议使用这种设置组合,有一天可能会完全禁止使用。

23 .3.3. 服务器和 Client 端之间的自动字符集转换

PostgreSQL 支持服务器和 Client 端之间针对某些字符集组合的自动字符集转换。转换信息存储在pg_conversion系统目录中。 PostgreSQL 带有一些 sched 义的转换,如Table 23.2所示。您可以使用 SQL 命令CREATE CONVERSION创建新的转换。

表 23.2Client 端/服务器字符集转换

服务器字符集可用的 Client 端字符集
BIG5不支持作为服务器编码
EUC_CN* EUC_CN *,MULE_INTERNALUTF8
EUC_JP* EUC_JP *,MULE_INTERNALSJISUTF8
EUC_JIS_2004* EUC_JIS_2004 *,SHIFT_JIS_2004UTF8
EUC_KR* EUC_KR *,MULE_INTERNALUTF8
EUC_TW* EUC_TW *,BIG5MULE_INTERNALUTF8
GB18030不支持作为服务器编码
GBK不支持作为服务器编码
ISO_8859_5* ISO_8859_5 *,KOI8RMULE_INTERNALUTF8WIN866WIN1251
ISO_8859_6* ISO_8859_6 *,UTF8
ISO_8859_7* ISO_8859_7 *,UTF8
ISO_8859_8* ISO_8859_8 *,UTF8
JOHAB不支持作为服务器编码
KOI8R* KOI8R *,ISO_8859_5MULE_INTERNALUTF8WIN866WIN1251
KOI8U* KOI8U *,UTF8
LATIN1* LATIN1 *,MULE_INTERNALUTF8
LATIN2* LATIN2 *,MULE_INTERNALUTF8WIN1250
LATIN3* LATIN3 *,MULE_INTERNALUTF8
LATIN4* LATIN4 *,MULE_INTERNALUTF8
LATIN5* LATIN5 *,UTF8
LATIN6* LATIN6 *,UTF8
LATIN7* LATIN7 *,UTF8
LATIN8* LATIN8 *,UTF8
LATIN9* LATIN9 *,UTF8
LATIN10* LATIN10 *,UTF8
MULE_INTERNAL* MULE_INTERNAL *,BIG5EUC_CNEUC_JPEUC_KREUC_TWISO_8859_5KOI8RLATIN1LATIN4SJISWIN866WIN1250WIN1251
SJIS不支持作为服务器编码
SHIFT_JIS_2004不支持作为服务器编码
SQL_ASCII任何(不执行任何转换)
UHC不支持作为服务器编码
UTF8所有支持的编码
WIN866* WIN866 *,ISO_8859_5KOI8RMULE_INTERNALUTF8WIN1251
WIN874* WIN874 *,UTF8
WIN1250* WIN1250 *,LATIN2MULE_INTERNALUTF8
WIN1251* WIN1251 *,ISO_8859_5KOI8RMULE_INTERNALUTF8WIN866
WIN1252* WIN1252 *,UTF8
WIN1253* WIN1253 *,UTF8
WIN1254* WIN1254 *,UTF8
WIN1255* WIN1255 *,UTF8
WIN1256* WIN1256 *,UTF8
WIN1257* WIN1257 *,UTF8
WIN1258* WIN1258 *,UTF8

要启用自动字符集转换,您必须告诉 PostgreSQL 您想在 Client 端中使用的字符集(编码)。有几种方法可以实现此目的:

  • 在 psql 中使用\encoding命令。 \encoding允许您即时更改 Client 端编码。例如,要将编码更改为SJIS,请 Importing:
\encoding SJIS
  • libpq(Section 34.10)具有控制 Client 端编码的功能。

  • 使用SET client_encoding TO。可以使用以下 SQL 命令来设置 Client 端编码:

SET CLIENT_ENCODING TO 'value';

您也可以为此使用标准 SQL 语法SET NAMES

SET NAMES 'value';

要查询当前的 Client 端编码:

SHOW client_encoding;

要返回默认编码:

RESET client_encoding;
  • 使用PGCLIENTENCODING。如果在 Client 端环境中定义了环境变量PGCLIENTENCODING,则在与服务器构建连接时会自动选择该 Client 端编码。 (随后可以使用上述任何其他方法覆盖此方法.)

  • 使用配置变量client_encoding。如果设置了client_encoding变量,则在与服务器构建连接时会自动选择该 Client 端编码。 (随后可以使用上述任何其他方法覆盖此方法.)

如果无法转换特定字符(假设您为服务器选择了EUC_JP,为 Client 端选择了LATIN1,并且返回了一些日语字符,但这些字符在LATIN1中没有表示),则会报告错误。

如果 Client 端字符集定义为SQL_ASCII,则无论服务器的字符集如何,都将禁用编码转换。和服务器一样,除非使用全 ASCII 数据,否则使用SQL_ASCII是不明智的。

23 .3.4. 进一步阅读

这些都是开始学习各种编码系统的好资源。

    • CJKV 信息处理:中文,日文,韩文和越南文计算*
    • 包含EUC_JPEUC_CNEUC_KREUC_TW的详细说明。
  • http://www.unicode.org/

    • Unicodeunion 的网站。
  • RFC 3629

    • 此处定义了 UTF-8(8 位 UCS/Unicode 转换格式)。