20.2. 字符集支持 #
PostgreSQL中的字符集支持允许你以多种字符集存储文本,包括 ISO 8859 系列之类的单字节字符集,以及
EUC(扩展 Unix 编码)、Unicode 和 Mule 内部编码之类的多字节字符集。所有字符集都可以在整个服务器中透明地使用。(如果你使用来自其他来源的扩展函数,则取决于它们的代码编写得是否正确。)默认字符集是在使用
initdb初始化PostgreSQL
数据库集簇时选定的。在使用createdb创建数据库时,或者使用 SQL 命令CREATE DATABASE时,都可以覆盖该设置,因此你可以拥有多个数据库,并让每个数据库使用不同的字符集。
20.2.1. 支持的字符集 #
表 20.1显示了服务器中可用的字符集。
表 20.1. 服务器字符集
| 名称 | 描述 |
|---|---|
SQL_ASCII | ASCII |
EUC_JP | 日语 EUC |
EUC_CN | 中文 EUC |
EUC_KR | 韩语 EUC |
JOHAB | 韩语 EUC(Hangle 基) |
EUC_TW | 台湾 EUC |
UNICODE | Unicode(UTF-8) |
MULE_INTERNAL | Mule 内部编码 |
LATIN1 | ISO 8859-1/ECMA 94(拉丁字母表 1 号) |
LATIN2 | ISO 8859-2/ECMA 94(拉丁字母表 2 号) |
LATIN3 | ISO 8859-3/ECMA 94(拉丁字母表 3 号) |
LATIN4 | ISO 8859-4/ECMA 94(拉丁字母表 4 号) |
LATIN5 | ISO 8859-9/ECMA 128(拉丁字母表 5 号) |
LATIN6 | ISO 8859-10/ECMA 144(拉丁字母表 6 号) |
LATIN7 | ISO 8859-13(拉丁字母表 7 号) |
LATIN8 | ISO 8859-14(拉丁字母表 8 号) |
LATIN9 | ISO 8859-15(拉丁字母表 9 号) |
LATIN10 | ISO 8859-16/ASRO SR 14111(拉丁字母表 10 号) |
ISO_8859_5 | ISO 8859-5/ECMA 113(拉丁/西里尔) |
ISO_8859_6 | ISO 8859-6/ECMA 114(拉丁/阿拉伯) |
ISO_8859_7 | ISO 8859-7/ECMA 118(拉丁/希腊) |
ISO_8859_8 | ISO 8859-8/ECMA 121(拉丁/希伯来) |
KOI8 | KOI8-R(U) |
ALT | Windows CP866 |
WIN874 | Windows CP874(泰语) |
WIN1250 | Windows CP1250 |
WIN | Windows CP1251 |
WIN1256 | Windows CP1256(阿拉伯语) |
TCVN | TCVN-5712/Windows CP1258(越南语) |
重要
在PostgreSQL 7.2 之前,LATIN5
错误地表示 ISO 8859-5。从 7.2 开始,LATIN5表示
ISO 8859-9。如果你有一个在 7.1 或更早版本上创建的LATIN5
数据库,并且想要迁移到 7.2 或之后的版本,应当留意这一变化。
并非所有客户端API都支持上表中的全部字符集。例如,PostgreSQL JDBC 驱动就不支持
MULE_INTERNAL、LATIN6、LATIN8和LATIN10。
20.2.2. 设置字符集
initdb为PostgreSQL集簇定义默认字符集(编码)。例如:
initdb -E EUC_JP
这会把默认字符集设为EUC_JP(日语的扩展 Unix 编码)。如果你喜欢更长的选项形式,也可以用--encoding代替-E。如果未给出-E或
--encoding选项,则使用SQL_ASCII。
你可以创建使用不同字符集的数据库:
createdb -E EUC_KR korean
这将创建一个名为korean的数据库,它使用
EUC_KR字符集。另一种实现方式是使用以下 SQL 命令:
CREATE DATABASE korean WITH ENCODING 'EUC_KR';
数据库的编码存储在系统目录pg_database中。可以使用
psql的-l选项或\l命令查看。
$ psql -l
List of databases
Database | Owner | Encoding
---------------+---------+---------------
euc_cn | t-ishii | EUC_CN
euc_jp | t-ishii | EUC_JP
euc_kr | t-ishii | EUC_KR
euc_tw | t-ishii | EUC_TW
mule_internal | t-ishii | MULE_INTERNAL
regression | t-ishii | SQL_ASCII
template1 | t-ishii | EUC_JP
test | t-ishii | EUC_JP
unicode | t-ishii | UNICODE
(9 rows)
重要
虽然你可以为数据库指定任何想要的编码,但选择一个与所选区域设置所期望的编码不一致的编码是不明智的。LC_COLLATE和
LC_CTYPE设置隐含着一种特定的编码,依赖区域的操作(例如排序)很可能会错误解释以不兼容编码存储的数据。
由于这些区域设置被initdb冻结,在同一集簇的不同数据库中使用不同编码的表面灵活性,与其说是真实的,不如说是理论上的。这些机制将来很可能会在 PostgreSQL的未来版本中被重新考虑。
安全使用多种编码的一种办法,是在initdb时把区域设置设为C或POSIX,从而禁用任何真正的区域感知。
20.2.3. 服务器和客户端之间的自动字符集转换
PostgreSQL 支持在服务器和客户端之间,对某些字符集进行自动字符集转换。转换信息保存在系统目录 pg_conversion 中。可以使用 SQL 命令 CREATE CONVERSION 创建新的转换。PostgreSQL 自带了一些预定义转换,它们列于表 20.2。
表 20.2. 客户端/服务器字符集转换
| 服务器字符集 | 可用的客户端字符集 |
|---|---|
SQL_ASCII | SQL_ASCII, UNICODE, MULE_INTERNAL
|
EUC_JP | EUC_JP, SJIS,
UNICODE, MULE_INTERNAL
|
EUC_CN | EUC_CN, UNICODE, MULE_INTERNAL
|
EUC_KR | EUC_KR, UNICODE, MULE_INTERNAL
|
JOHAB | JOHAB, UNICODE
|
EUC_TW | EUC_TW, BIG5,
UNICODE, MULE_INTERNAL
|
LATIN1 | LATIN1, UNICODE
MULE_INTERNAL
|
LATIN2 | LATIN2, WIN1250,
UNICODE,
MULE_INTERNAL
|
LATIN3 | LATIN3, UNICODE,
MULE_INTERNAL
|
LATIN4 | LATIN4, UNICODE,
MULE_INTERNAL
|
LATIN5 | LATIN5, UNICODE
|
LATIN6 | LATIN6, UNICODE,
MULE_INTERNAL
|
LATIN7 | LATIN7, UNICODE,
MULE_INTERNAL
|
LATIN8 | LATIN8, UNICODE,
MULE_INTERNAL
|
LATIN9 | LATIN9, UNICODE,
MULE_INTERNAL
|
LATIN10 | LATIN10, UNICODE,
MULE_INTERNAL
|
ISO_8859_5 | ISO_8859_5,
UNICODE,
MULE_INTERNAL,
WIN,
ALT,
KOI8
|
ISO_8859_6 | ISO_8859_6,
UNICODE
|
ISO_8859_7 | ISO_8859_7,
UNICODE
|
ISO_8859_8 | ISO_8859_8,
UNICODE
|
UNICODE | EUC_JP, SJIS,
EUC_KR, UHC, JOHAB,
EUC_CN, GBK,
EUC_TW, BIG5,
LATIN1 到 LATIN10,
ISO_8859_5,
ISO_8859_6,
ISO_8859_7,
ISO_8859_8,
WIN, ALT,
KOI8,
WIN1256,
TCVN,
WIN874,
GB18030,
WIN1250
|
MULE_INTERNAL | EUC_JP, SJIS, EUC_KR, EUC_CN,
EUC_TW, BIG5, LATIN1 到 LATIN5,
WIN, ALT,
WIN1250,
BIG5, ISO_8859_5, KOI8
|
KOI8 | ISO_8859_5, WIN,
ALT, KOI8,
UNICODE, MULE_INTERNAL
|
ALT | ISO_8859_5, WIN,
ALT, KOI8,
UNICODE, MULE_INTERNAL
|
WIN874 | WIN874,
UNICODE
|
WIN1250 | LATIN2, WIN1250,
UNICODE, MULE_INTERNAL
|
WIN | ISO_8859_5, WIN,
ALT, KOI8,
UNICODE, MULE_INTERNAL
|
WIN1256 | WIN1256,
UNICODE
|
TCVN | TCVN,
UNICODE
|
若要启用这种自动字符集转换,必须告诉PostgreSQL 你希望客户端使用哪种字符集(编码)。有几种方法可以做到这一点:
在psql中使用
\encoding命令。\encoding允许动态更改客户端编码。例如,要把编码改成SJIS,可以输入:\encoding SJIS
使用libpq函数。
\encoding实际上就是为达到这一目的而调用PQsetClientEncoding()。int PQsetClientEncoding(PGconn *
conn, const char *encoding);其中
conn是到服务器的连接,而encoding是你想使用的编码。如果该函数成功设置了编码,它返回 0,否则返回 -1。此连接的当前编码可以用下面的函数确定:int PQclientEncoding(const PGconn *
conn);注意,它返回的是编码 ID,而不是像
EUC_JP这样的符号字符串。要把编码 ID 转换为编码名,可以用:char *pg_encoding_to_char(int
encoding_id);使用
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——
此时该字符会被转换为带括号的十六进制字节值,例如
(826C)。
20.2.4. 进一步阅读
这些都是开始了解各种编码系统的良好资料。
- ftp://ftp.ora.com/pub/examples/nutshell/ujip/doc/cjk.inf
其中对
EUC_JP、EUC_CN、EUC_KR和EUC_TW的详细说明见第 3.2 节。- http://www.unicode.org/
Unicode Consortium 网站。
- RFC 2044
UTF-8 在这里定义。