PostgreSQL中的字符集支持允许你以多种字符集 (也称为编码)存储文本,包括 ISO 8859 系列之类的单字节字符集,以及 EUC(扩展 Unix 编码)、UTF-8 和 Mule 内部编 码等多字节字符集。所有受支持的字符集都可以被客户端透明地使用,但其中少 数不支持在服务器内部使用(即不能作为服务器端编码)。默认字符集是在使用 initdb初始化PostgreSQL 数据库集簇时选定的。创建数据库时可以覆盖该设置,因此你可以拥有多个数据 库,并让每个数据库使用不同的字符集。
不过,一项重要限制是,每个数据库的字符集必须与数据库的 LC_CTYPE(字符分类)和 LC_COLLATE(字符串排序顺序)区域设置兼容。对于 C 或 POSIX 区域设置,允许使用任何字符集;对于 libc 提供的其他区域设置,只有一种字符集能够正确工作。(但在 Windows 上,UTF-8 编码可以与任何区域设置一起使用。)如果配置了 ICU 支持,ICU 提供的区域设置可以与大多数服务器端编码一起使用,但并非全部。
Table 23.1显示了PostgreSQL中可用的字符集。
Table 23.1. 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-3 | |
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 字符。
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)
在大多数现代操作系统上,PostgreSQL能够 判断LC_CTYPE设置所隐含的字符集,并强制只允许使用与之 匹配的数据库编码。在较老的系统上,你需要自行确保所用编码正是所选区域 设置期望的编码。这里的错误很可能会导致区域设置相关操作(例如排序)出 现奇怪的行为。
即使LC_CTYPE不是C或 POSIX,PostgreSQL 仍允许超级用户创建使用SQL_ASCII编码的数据库。正如 前文所述,SQL_ASCII并不强制数据库中存储的数据具 有任何特定编码,因此这种选择存在区域设置相关误行为的风险。这种设置组 合已经被弃用,未来某一天可能会被完全禁止。
PostgreSQL 支持在服务器和客户端之间,对某些字符集组合进行自动字符集转换。转换信息保存在系统目录 pg_conversion 中。PostgreSQL 提供了一些预定义转换,如 Table 23.2 所示。可以使用 SQL 命令 CREATE CONVERSION 创建新的转换。
Table 23.2. 客户端/服务器字符集转换
| 服务器字符集 | 可用的客户端字符集 |
|---|---|
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 |
若要启用自动字符集转换,必须告诉PostgreSQL 你希望客户端使用哪种字符集(编码)。有几种方法可以做到这一点:
在psql中使用\encoding 命令。\encoding允许动态更改客户端编码。例如,要把 编码改成SJIS,可以输入:
\encoding SJIS
libpq(Section 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 是不明智的。
这些都是开始了解各种编码系统的良好资料。
其中对EUC_JP、EUC_CN、 EUC_KR和EUC_TW做了详细说明。
Unicode Consortium 网站。
这里定义了UTF-8(8 位 UCS/Unicode 转换格式)。