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.3 显示了 PostgreSQL 中可用的字符集。
表 23.3. PostgreSQL 字符集
| 名称 | 描述 | 语言 | 是否服务器端? | ICU? | 字节/字符 | 别名 |
|---|---|---|---|---|---|---|
BIG5 | Big Five | 繁体中文 | 否 | 否 | 1–2 | WIN950, 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 | 国家标准 | 中文 | 否 | 否 | 1–4 | |
GBK | 扩展国家标准 | 简体中文 | 否 | 否 | 1–2 | WIN936, Windows936 |
ISO_8859_5 | ISO 8859-5, ECMA 113 | 拉丁字母/西里尔字母 | 是 | 是 | 1 | |
ISO_8859_6 | ISO 8859-6, ECMA 114 | 拉丁字母/阿拉伯字母 | 是 | 是 | 1 | |
ISO_8859_7 | ISO 8859-7, ECMA 118 | 拉丁字母/希腊字母 | 是 | 是 | 1 | |
ISO_8859_8 | ISO 8859-8, ECMA 121 | 拉丁字母/希伯来字母 | 是 | 是 | 1 | |
JOHAB | JOHAB | 韩语(谚文) | 否 | 否 | 1–3 | |
KOI8R | KOI8-R | 西里尔字母(俄语) | 是 | 是 | 1 | KOI8 |
KOI8U | KOI8-U | 西里尔字母(乌克兰语) | 是 | 是 | 1 | |
LATIN1 | ISO 8859-1, ECMA 94 | 西欧 | 是 | 是 | 1 | ISO88591 |
LATIN2 | ISO 8859-2, ECMA 94 | 中欧 | 是 | 是 | 1 | ISO88592 |
LATIN3 | ISO 8859-3, ECMA 94 | 南欧 | 是 | 是 | 1 | ISO88593 |
LATIN4 | ISO 8859-4, ECMA 94 | 北欧 | 是 | 是 | 1 | ISO88594 |
LATIN5 | ISO 8859-9, ECMA 128 | 土耳其语 | 是 | 是 | 1 | ISO88599 |
LATIN6 | ISO 8859-10, ECMA 144 | 北欧 | 是 | 是 | 1 | ISO885910 |
LATIN7 | ISO 8859-13 | 波罗的海 | 是 | 是 | 1 | ISO885913 |
LATIN8 | ISO 8859-14 | 凯尔特语 | 是 | 是 | 1 | ISO885914 |
LATIN9 | ISO 8859-15 | 带欧元符号和重音字符的 LATIN1 | 是 | 是 | 1 | ISO885915 |
LATIN10 | ISO 8859-16, ASRO SR 14111 | 罗马尼亚语 | 是 | 否 | 1 | ISO885916 |
MULE_INTERNAL | Mule 内部编码 | 多语种 Emacs | 是 | 否 | 1–4 | |
SJIS | Shift JIS | 日语 | 否 | 否 | 1–2 | Mskanji, ShiftJIS, WIN932, Windows932 |
SHIFT_JIS_2004 | Shift JIS, JIS X 0213 | 日语 | 否 | 否 | 1–2 | |
SQL_ASCII | 未指定(见正文) | 任意 | 是 | 否 | 1 | |
UHC | 统一谚文编码 | 韩语 | 否 | 否 | 1–2 | WIN949, Windows949 |
UTF8 | Unicode,8 位 | 所有 | 是 | 是 | 1–4 | Unicode |
WIN866 | Windows CP866 | 西里尔字母 | 是 | 是 | 1 | ALT |
WIN874 | Windows CP874 | 泰语 | 是 | 否 | 1 | |
WIN1250 | Windows CP1250 | 中欧 | 是 | 是 | 1 | |
WIN1251 | Windows CP1251 | 西里尔字母 | 是 | 是 | 1 | WIN |
WIN1252 | Windows CP1252 | 西欧 | 是 | 是 | 1 | |
WIN1253 | Windows CP1253 | 希腊语 | 是 | 是 | 1 | |
WIN1254 | Windows CP1254 | 土耳其语 | 是 | 是 | 1 | |
WIN1255 | Windows CP1255 | 希伯来语 | 是 | 是 | 1 | |
WIN1256 | Windows CP1256 | 阿拉伯语 | 是 | 是 | 1 | |
WIN1257 | Windows CP1257 | 波罗的海 | 是 | 是 | 1 | |
WIN1258 | Windows CP1258 | 越南语 | 是 | 是 | 1 | ABC, 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 支持针对多种字符集组合在服务器和客户端之间自动进行字符集转换(哪些组合可用,见第 23.3.4 节)。
若要启用自动字符集转换,必须告诉 PostgreSQL 你希望客户端使用哪种字符集(编码)。有几种方法可以做到这一点:
在 psql 中使用
\encoding命令。\encoding允许动态更改客户端编码。例如,要把编码改成SJIS,可以输入:\encoding SJIS
libpq(第 32.11 节)提供了控制客户端编码的函数。
使用
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_CN | EUC_CN,
MULE_INTERNAL,
UTF8
|
EUC_JP | EUC_JP,
MULE_INTERNAL,
SJIS,
UTF8
|
EUC_JIS_2004 | EUC_JIS_2004,
SHIFT_JIS_2004,
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 | 不支持作为服务器编码 |
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 至 LATIN4,
SJIS,
WIN866,
WIN1250,
WIN1251
|
SJIS | 不支持作为服务器编码 |
SHIFT_JIS_2004 | 不支持作为服务器编码 |
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
|
表 23.5. 所有内置字符集转换
| 转换名称 [a] | 源编码 | 目标编码 |
|---|---|---|
big5_to_euc_tw | BIG5 | EUC_TW |
big5_to_mic | BIG5 | MULE_INTERNAL |
big5_to_utf8 | BIG5 | UTF8 |
euc_cn_to_mic | EUC_CN | MULE_INTERNAL |
euc_cn_to_utf8 | EUC_CN | UTF8 |
euc_jp_to_mic | EUC_JP | MULE_INTERNAL |
euc_jp_to_sjis | EUC_JP | SJIS |
euc_jp_to_utf8 | EUC_JP | UTF8 |
euc_kr_to_mic | EUC_KR | MULE_INTERNAL |
euc_kr_to_utf8 | EUC_KR | UTF8 |
euc_tw_to_big5 | EUC_TW | BIG5 |
euc_tw_to_mic | EUC_TW | MULE_INTERNAL |
euc_tw_to_utf8 | EUC_TW | UTF8 |
gb18030_to_utf8 | GB18030 | UTF8 |
gbk_to_utf8 | GBK | UTF8 |
iso_8859_10_to_utf8 | LATIN6 | UTF8 |
iso_8859_13_to_utf8 | LATIN7 | UTF8 |
iso_8859_14_to_utf8 | LATIN8 | UTF8 |
iso_8859_15_to_utf8 | LATIN9 | UTF8 |
iso_8859_16_to_utf8 | LATIN10 | UTF8 |
iso_8859_1_to_mic | LATIN1 | MULE_INTERNAL |
iso_8859_1_to_utf8 | LATIN1 | UTF8 |
iso_8859_2_to_mic | LATIN2 | MULE_INTERNAL |
iso_8859_2_to_utf8 | LATIN2 | UTF8 |
iso_8859_2_to_windows_1250 | LATIN2 | WIN1250 |
iso_8859_3_to_mic | LATIN3 | MULE_INTERNAL |
iso_8859_3_to_utf8 | LATIN3 | UTF8 |
iso_8859_4_to_mic | LATIN4 | MULE_INTERNAL |
iso_8859_4_to_utf8 | LATIN4 | UTF8 |
iso_8859_5_to_koi8_r | ISO_8859_5 | KOI8R |
iso_8859_5_to_mic | ISO_8859_5 | MULE_INTERNAL |
iso_8859_5_to_utf8 | ISO_8859_5 | UTF8 |
iso_8859_5_to_windows_1251 | ISO_8859_5 | WIN1251 |
iso_8859_5_to_windows_866 | ISO_8859_5 | WIN866 |
iso_8859_6_to_utf8 | ISO_8859_6 | UTF8 |
iso_8859_7_to_utf8 | ISO_8859_7 | UTF8 |
iso_8859_8_to_utf8 | ISO_8859_8 | UTF8 |
iso_8859_9_to_utf8 | LATIN5 | UTF8 |
johab_to_utf8 | JOHAB | UTF8 |
koi8_r_to_iso_8859_5 | KOI8R | ISO_8859_5 |
koi8_r_to_mic | KOI8R | MULE_INTERNAL |
koi8_r_to_utf8 | KOI8R | UTF8 |
koi8_r_to_windows_1251 | KOI8R | WIN1251 |
koi8_r_to_windows_866 | KOI8R | WIN866 |
koi8_u_to_utf8 | KOI8U | UTF8 |
mic_to_big5 | MULE_INTERNAL | BIG5 |
mic_to_euc_cn | MULE_INTERNAL | EUC_CN |
mic_to_euc_jp | MULE_INTERNAL | EUC_JP |
mic_to_euc_kr | MULE_INTERNAL | EUC_KR |
mic_to_euc_tw | MULE_INTERNAL | EUC_TW |
mic_to_iso_8859_1 | MULE_INTERNAL | LATIN1 |
mic_to_iso_8859_2 | MULE_INTERNAL | LATIN2 |
mic_to_iso_8859_3 | MULE_INTERNAL | LATIN3 |
mic_to_iso_8859_4 | MULE_INTERNAL | LATIN4 |
mic_to_iso_8859_5 | MULE_INTERNAL | ISO_8859_5 |
mic_to_koi8_r | MULE_INTERNAL | KOI8R |
mic_to_sjis | MULE_INTERNAL | SJIS |
mic_to_windows_1250 | MULE_INTERNAL | WIN1250 |
mic_to_windows_1251 | MULE_INTERNAL | WIN1251 |
mic_to_windows_866 | MULE_INTERNAL | WIN866 |
sjis_to_euc_jp | SJIS | EUC_JP |
sjis_to_mic | SJIS | MULE_INTERNAL |
sjis_to_utf8 | SJIS | UTF8 |
windows_1258_to_utf8 | WIN1258 | UTF8 |
uhc_to_utf8 | UHC | UTF8 |
utf8_to_big5 | UTF8 | BIG5 |
utf8_to_euc_cn | UTF8 | EUC_CN |
utf8_to_euc_jp | UTF8 | EUC_JP |
utf8_to_euc_kr | UTF8 | EUC_KR |
utf8_to_euc_tw | UTF8 | EUC_TW |
utf8_to_gb18030 | UTF8 | GB18030 |
utf8_to_gbk | UTF8 | GBK |
utf8_to_iso_8859_1 | UTF8 | LATIN1 |
utf8_to_iso_8859_10 | UTF8 | LATIN6 |
utf8_to_iso_8859_13 | UTF8 | LATIN7 |
utf8_to_iso_8859_14 | UTF8 | LATIN8 |
utf8_to_iso_8859_15 | UTF8 | LATIN9 |
utf8_to_iso_8859_16 | UTF8 | LATIN10 |
utf8_to_iso_8859_2 | UTF8 | LATIN2 |
utf8_to_iso_8859_3 | UTF8 | LATIN3 |
utf8_to_iso_8859_4 | UTF8 | LATIN4 |
utf8_to_iso_8859_5 | UTF8 | ISO_8859_5 |
utf8_to_iso_8859_6 | UTF8 | ISO_8859_6 |
utf8_to_iso_8859_7 | UTF8 | ISO_8859_7 |
utf8_to_iso_8859_8 | UTF8 | ISO_8859_8 |
utf8_to_iso_8859_9 | UTF8 | LATIN5 |
utf8_to_johab | UTF8 | JOHAB |
utf8_to_koi8_r | UTF8 | KOI8R |
utf8_to_koi8_u | UTF8 | KOI8U |
utf8_to_sjis | UTF8 | SJIS |
utf8_to_windows_1258 | UTF8 | WIN1258 |
utf8_to_uhc | UTF8 | UHC |
utf8_to_windows_1250 | UTF8 | WIN1250 |
utf8_to_windows_1251 | UTF8 | WIN1251 |
utf8_to_windows_1252 | UTF8 | WIN1252 |
utf8_to_windows_1253 | UTF8 | WIN1253 |
utf8_to_windows_1254 | UTF8 | WIN1254 |
utf8_to_windows_1255 | UTF8 | WIN1255 |
utf8_to_windows_1256 | UTF8 | WIN1256 |
utf8_to_windows_1257 | UTF8 | WIN1257 |
utf8_to_windows_866 | UTF8 | WIN866 |
utf8_to_windows_874 | UTF8 | WIN874 |
windows_1250_to_iso_8859_2 | WIN1250 | LATIN2 |
windows_1250_to_mic | WIN1250 | MULE_INTERNAL |
windows_1250_to_utf8 | WIN1250 | UTF8 |
windows_1251_to_iso_8859_5 | WIN1251 | ISO_8859_5 |
windows_1251_to_koi8_r | WIN1251 | KOI8R |
windows_1251_to_mic | WIN1251 | MULE_INTERNAL |
windows_1251_to_utf8 | WIN1251 | UTF8 |
windows_1251_to_windows_866 | WIN1251 | WIN866 |
windows_1252_to_utf8 | WIN1252 | UTF8 |
windows_1256_to_utf8 | WIN1256 | UTF8 |
windows_866_to_iso_8859_5 | WIN866 | ISO_8859_5 |
windows_866_to_koi8_r | WIN866 | KOI8R |
windows_866_to_mic | WIN866 | MULE_INTERNAL |
windows_866_to_utf8 | WIN866 | UTF8 |
windows_866_to_windows_1251 | WIN866 | WIN |
windows_874_to_utf8 | WIN874 | UTF8 |
euc_jis_2004_to_utf8 | EUC_JIS_2004 | UTF8 |
utf8_to_euc_jis_2004 | UTF8 | EUC_JIS_2004 |
shift_jis_2004_to_utf8 | SHIFT_JIS_2004 | UTF8 |
utf8_to_shift_jis_2004 | UTF8 | SHIFT_JIS_2004 |
euc_jis_2004_to_shift_jis_2004 | EUC_JIS_2004 | SHIFT_JIS_2004 |
shift_jis_2004_to_euc_jis_2004 | SHIFT_JIS_2004 | EUC_JIS_2004 |
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 转换格式)。
报告文档问题
阅读 上游文档. 通过 PostgreSQL 文档反馈表单.