↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1
历史版本。 PostgreSQL 11 已结束支持。 2023-11-09. 请参阅 当前版本手册.

23.3. 字符集支持 #

PostgreSQL 中的字符集支持允许你以多种字符集(也称为编码)存储文本,包括 ISO 8859 系列之类的单字节字符集,以及 EUC(扩展 Unix 编码)、UTF-8 和 Mule 内部编码等多字节字符集。所有受支持的字符集都可以被客户端透明地使用,但其中少数不支持在服务器内部使用(即不能作为服务器端编码)。默认字符集是在使用 initdb 初始化 PostgreSQL 数据库集簇时选定的。创建数据库时可以覆盖该设置,因此你可以拥有多个数据库,并让每个数据库使用不同的字符集。

不过,一个重要限制是,每个数据库的字符集必须与该数据库的 LC_CTYPE(字符分类)和 LC_COLLATE(字符串排序顺序)区域设置兼容。对于 C 或 POSIX 区域设置,任何字符集都可以使用;但对于其他由 libc 提供的区域设置,只有一种字符集能够正确工作。(不过在 Windows 上,UTF-8 编码可以与任何区域设置配合使用。)如果配置了 ICU 支持,则 ICU 提供的区域设置可用于大多数(但不是全部)服务器端编码。

23.3.1. 支持的字符集 #

表 23.1 显示了 PostgreSQL 中可用的字符集。

表 23.1. PostgreSQL 字符集

名称描述语言是否服务器端?ICU?字节数/字符别名
BIG5Big Five繁体中文否否1-2WIN950, Windows950
EUC_CN扩展 Unix 编码 -CN简体中文是是1-3 
EUC_JP扩展 Unix 编码 -JP日语是是1-3 
EUC_JIS_2004扩展 Unix 编码 -JP,JIS X 0213日语是否1-3 
EUC_KR扩展 Unix 编码 -KR韩语是是1-3 
EUC_TW扩展 Unix 编码 -TW繁体中文、台湾语是是1-3 
GB18030国家标准中文否否1-4 
GBK扩展国家标准简体中文否否1-2WIN936, Windows936
ISO_8859_5ISO 8859-5, ECMA 113拉丁字母/西里尔字母是是1 
ISO_8859_6ISO 8859-6, ECMA 114拉丁字母/阿拉伯字母是是1 
ISO_8859_7ISO 8859-7, ECMA 118拉丁字母/希腊字母是是1 
ISO_8859_8ISO 8859-8, ECMA 121拉丁字母/希伯来字母是是1 
JOHABJOHAB韩语(谚文)否否1-3 
KOI8RKOI8-R西里尔字母(俄语)是是1KOI8
KOI8UKOI8-U西里尔字母(乌克兰语)是是1 
LATIN1ISO 8859-1, ECMA 94西欧是是1ISO88591
LATIN2ISO 8859-2, ECMA 94中欧是是1ISO88592
LATIN3ISO 8859-3, ECMA 94南欧是是1ISO88593
LATIN4ISO 8859-4, ECMA 94北欧是是1ISO88594
LATIN5ISO 8859-9, ECMA 128土耳其语是是1ISO88599
LATIN6ISO 8859-10, ECMA 144北欧是是1ISO885910
LATIN7ISO 8859-13波罗的海是是1ISO885913
LATIN8ISO 8859-14凯尔特语是是1ISO885914
LATIN9ISO 8859-15带欧元符号和重音字符的 LATIN1是是1ISO885915
LATIN10ISO 8859-16, ASRO SR 14111罗马尼亚语是否1ISO885916
MULE_INTERNALMule 内部编码多语种 Emacs是否1-4 
SJISShift JIS日语否否1-2Mskanji, ShiftJIS, WIN932, Windows932
SHIFT_JIS_2004Shift JIS, JIS X 0213日语否否1-2 
SQL_ASCII未指定(见正文)任意是否1 
UHC统一谚文编码韩语否否1-2WIN949, Windows949
UTF8Unicode,8 位所有是是1-4Unicode
WIN866Windows CP866西里尔字母是是1ALT
WIN874Windows CP874泰语是否1 
WIN1250Windows CP1250中欧是是1 
WIN1251Windows CP1251西里尔字母是是1WIN
WIN1252Windows CP1252西欧是是1 
WIN1253Windows CP1253希腊语是是1 
WIN1254Windows CP1254土耳其语是是1 
WIN1255Windows CP1255希伯来语是是1 
WIN1256Windows CP1256阿拉伯语是是1 
WIN1257Windows CP1257波罗的海是是1 
WIN1258Windows CP1258越南语是是1ABC, TCVN, TCVN5712, VSCII

并非所有客户端 API 都支持上表中的全部字符集。例如,PostgreSQL JDBC 驱动就不支持 MULE_INTERNAL、LATIN6、LATIN8 和 LATIN10。

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 数据库。复制其他任何数据库时,新数据库的编码和区域设置都必须与源数据库一致,否则可能导致数据损坏。详见第 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)

重要

在大多数现代操作系统上,PostgreSQL 能够判断 LC_CTYPE 设置所隐含的字符集,并强制只允许使用与之匹配的数据库编码。在较老的系统上,你需要自行确保所用编码正是所选区域设置期望的编码。这里的错误很可能会导致区域设置相关操作(例如排序)出现奇怪的行为。

即使 LC_CTYPE 不是 C 或 POSIX,PostgreSQL 仍允许超级用户创建使用 SQL_ASCII 编码的数据库。正如前文所述,SQL_ASCII 并不强制数据库中存储的数据具有任何特定编码,因此这种选择存在区域设置相关误行为的风险。这种设置组合已经被弃用,未来某一天可能会被完全禁止。

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

PostgreSQL 支持在服务器和客户端之间,对某些字符集组合进行自动字符集转换。转换信息保存在系统目录 pg_conversion 中。PostgreSQL 提供了一些预定义转换,如表 23.2 所示。可以使用 SQL 命令 CREATE CONVERSION 创建新的转换。

表 23.2. 客户端/服务器字符集转换

服务器字符集可用的客户端字符集
BIG5不支持作为服务器编码
EUC_CNEUC_CN, MULE_INTERNAL, UTF8
EUC_JPEUC_JP, MULE_INTERNAL, SJIS, UTF8
EUC_JIS_2004EUC_JIS_2004, SHIFT_JIS_2004, 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
JOHAB不支持作为服务器编码
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 至 LATIN4, SJIS, WIN866, WIN1250, WIN1251
SJIS不支持作为服务器编码
SHIFT_JIS_2004不支持作为服务器编码
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 你希望客户端使用哪种字符集(编码)。有几种方法可以做到这一点:

  • 在 psql 中使用\encoding 命令。\encoding 允许动态更改客户端编码。例如,要把编码改成 SJIS,可以输入:

    \encoding SJIS
    

  • libpq(第 34.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 是不明智的。

23.3.4. 进一步阅读

以下资料是了解各种编码系统的良好起点。

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

其中对 EUC_JP、EUC_CN、EUC_KR 和 EUC_TW 做了详细说明。

http://www.unicode.org/

Unicode Consortium 网站。

RFC 3629

这里定义了 UTF-8(8 位 UCS/Unicode 转换格式)。

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.