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

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 20devel 尚未正式发布,内容仍可能变化。

23.3. 字符集支持 #

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

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

23.3.1. 支持的字符集 #

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

表 23.3. 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–4 
GB18030国家标准,2022 版中文否否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
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 驱动就不支持 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 支持针对多种字符集组合在服务器和客户端之间自动进行字符集转换(哪些组合可用,见第 23.3.4 节)。

若要启用自动字符集转换,必须告诉 PostgreSQL 你希望客户端使用哪种字符集(编码)。有几种方法可以做到这一点:

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

    \encoding SJIS
    

  • libpq(第 32.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,那么无论服务器字符集是什么,编码转换都会被禁用。(但是,如果服务器字符集不是 SQL_ASCII,服务器仍会检查传入数据对该编码是否有效,因此最终效果相当于客户端字符集与服务器字符集相同。)和服务器端一样,除非你处理的全部都是 ASCII 数据,否则使用 SQL_ASCII 并不明智。

23.3.4. 可用的字符集转换 #

PostgreSQL 允许在 pg_conversion 系统目录中列有转换函数的任意两个字符集之间进行转换。PostgreSQL 自带了一些预定义转换,概况见表 23.4,更详细的信息见表 23.5。你也可以使用 SQL 命令 CREATE CONVERSION 创建新的转换。(若要用于自动的客户端/服务器转换,该字符集对的转换必须被标记为“default”。)

表 23.4. 内置客户端/服务器字符集转换

服务器字符集可用的客户端字符集
BIG5不支持作为服务器编码
EUC_CNEUC_CN, UTF8
EUC_JPEUC_JP, SJIS, UTF8
EUC_JIS_2004EUC_JIS_2004, SHIFT_JIS_2004, UTF8
EUC_KREUC_KR, UTF8
EUC_TWEUC_TW, BIG5, UTF8
GB18030不支持作为服务器编码
GBK不支持作为服务器编码
ISO_8859_5ISO_8859_5, KOI8R, 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, UTF8, WIN866, WIN1251
KOI8UKOI8U, UTF8
LATIN1LATIN1, UTF8
LATIN2LATIN2, UTF8, WIN1250
LATIN3LATIN3, UTF8
LATIN4LATIN4, UTF8
LATIN5LATIN5, UTF8
LATIN6LATIN6, UTF8
LATIN7LATIN7, UTF8
LATIN8LATIN8, UTF8
LATIN9LATIN9, UTF8
LATIN10LATIN10, UTF8
SJIS不支持作为服务器编码
SHIFT_JIS_2004不支持作为服务器编码
SQL_ASCII任何(不会执行转换)
UHC不支持作为服务器编码
UTF8所有受支持的编码
WIN866WIN866, ISO_8859_5, KOI8R, UTF8, WIN1251
WIN874WIN874, UTF8
WIN1250WIN1250, LATIN2, UTF8
WIN1251WIN1251, ISO_8859_5, KOI8R, UTF8, WIN866
WIN1252WIN1252, UTF8
WIN1253WIN1253, UTF8
WIN1254WIN1254, UTF8
WIN1255WIN1255, UTF8
WIN1256WIN1256, UTF8
WIN1257WIN1257, UTF8
WIN1258WIN1258, UTF8

表 23.5. 所有内置字符集转换

转换名称 [a] 源编码目标编码
big5_to_euc_twBIG5EUC_TW
big5_to_utf8BIG5UTF8
euc_cn_to_utf8EUC_CNUTF8
euc_jp_to_sjisEUC_JPSJIS
euc_jp_to_utf8EUC_JPUTF8
euc_kr_to_utf8EUC_KRUTF8
euc_tw_to_big5EUC_TWBIG5
euc_tw_to_utf8EUC_TWUTF8
gb18030_to_utf8GB18030UTF8
gbk_to_utf8GBKUTF8
iso_8859_10_to_utf8LATIN6UTF8
iso_8859_13_to_utf8LATIN7UTF8
iso_8859_14_to_utf8LATIN8UTF8
iso_8859_15_to_utf8LATIN9UTF8
iso_8859_16_to_utf8LATIN10UTF8
iso_8859_1_to_utf8LATIN1UTF8
iso_8859_2_to_utf8LATIN2UTF8
iso_8859_2_to_windows_1250LATIN2WIN1250
iso_8859_3_to_utf8LATIN3UTF8
iso_8859_4_to_utf8LATIN4UTF8
iso_8859_5_to_koi8_rISO_8859_5KOI8R
iso_8859_5_to_utf8ISO_8859_5UTF8
iso_8859_5_to_windows_1251ISO_8859_5WIN1251
iso_8859_5_to_windows_866ISO_8859_5WIN866
iso_8859_6_to_utf8ISO_8859_6UTF8
iso_8859_7_to_utf8ISO_8859_7UTF8
iso_8859_8_to_utf8ISO_8859_8UTF8
iso_8859_9_to_utf8LATIN5UTF8
johab_to_utf8JOHABUTF8
koi8_r_to_iso_8859_5KOI8RISO_8859_5
koi8_r_to_utf8KOI8RUTF8
koi8_r_to_windows_1251KOI8RWIN1251
koi8_r_to_windows_866KOI8RWIN866
koi8_u_to_utf8KOI8UUTF8
sjis_to_euc_jpSJISEUC_JP
sjis_to_utf8SJISUTF8
windows_1258_to_utf8WIN1258UTF8
uhc_to_utf8UHCUTF8
utf8_to_big5UTF8BIG5
utf8_to_euc_cnUTF8EUC_CN
utf8_to_euc_jpUTF8EUC_JP
utf8_to_euc_krUTF8EUC_KR
utf8_to_euc_twUTF8EUC_TW
utf8_to_gb18030UTF8GB18030
utf8_to_gbkUTF8GBK
utf8_to_iso_8859_1UTF8LATIN1
utf8_to_iso_8859_10UTF8LATIN6
utf8_to_iso_8859_13UTF8LATIN7
utf8_to_iso_8859_14UTF8LATIN8
utf8_to_iso_8859_15UTF8LATIN9
utf8_to_iso_8859_16UTF8LATIN10
utf8_to_iso_8859_2UTF8LATIN2
utf8_to_iso_8859_3UTF8LATIN3
utf8_to_iso_8859_4UTF8LATIN4
utf8_to_iso_8859_5UTF8ISO_8859_5
utf8_to_iso_8859_6UTF8ISO_8859_6
utf8_to_iso_8859_7UTF8ISO_8859_7
utf8_to_iso_8859_8UTF8ISO_8859_8
utf8_to_iso_8859_9UTF8LATIN5
utf8_to_johabUTF8JOHAB
utf8_to_koi8_rUTF8KOI8R
utf8_to_koi8_uUTF8KOI8U
utf8_to_sjisUTF8SJIS
utf8_to_windows_1258UTF8WIN1258
utf8_to_uhcUTF8UHC
utf8_to_windows_1250UTF8WIN1250
utf8_to_windows_1251UTF8WIN1251
utf8_to_windows_1252UTF8WIN1252
utf8_to_windows_1253UTF8WIN1253
utf8_to_windows_1254UTF8WIN1254
utf8_to_windows_1255UTF8WIN1255
utf8_to_windows_1256UTF8WIN1256
utf8_to_windows_1257UTF8WIN1257
utf8_to_windows_866UTF8WIN866
utf8_to_windows_874UTF8WIN874
windows_1250_to_iso_8859_2WIN1250LATIN2
windows_1250_to_utf8WIN1250UTF8
windows_1251_to_iso_8859_5WIN1251ISO_8859_5
windows_1251_to_koi8_rWIN1251KOI8R
windows_1251_to_utf8WIN1251UTF8
windows_1251_to_windows_866WIN1251WIN866
windows_1252_to_utf8WIN1252UTF8
windows_1256_to_utf8WIN1256UTF8
windows_866_to_iso_8859_5WIN866ISO_8859_5
windows_866_to_koi8_rWIN866KOI8R
windows_866_to_utf8WIN866UTF8
windows_866_to_windows_1251WIN866WIN
windows_874_to_utf8WIN874UTF8
euc_jis_2004_to_utf8EUC_JIS_2004UTF8
utf8_to_euc_jis_2004UTF8EUC_JIS_2004
shift_jis_2004_to_utf8SHIFT_JIS_2004UTF8
utf8_to_shift_jis_2004UTF8SHIFT_JIS_2004
euc_jis_2004_to_shift_jis_2004EUC_JIS_2004SHIFT_JIS_2004
shift_jis_2004_to_euc_jis_2004SHIFT_JIS_2004EUC_JIS_2004

[a] 转换名称遵循标准命名模式:源编码的正式名称,其中所有非字母数字字符都替换为下划线,后跟_to_,再跟以相同方式处理后的目标编码名称。因此,这些名称有时会与表 23.3 中显示的惯用编码名称不同。


23.3.5. 进一步阅读 #

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

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

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

https://www.unicode.org/

Unicode Consortium 网站。

RFC 3629

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

报告文档问题

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