PostgreSQL里面的字符集支持你能够以各种字符集存储文本,包括单字节字符集,比如 ISO 8859 系列,以及多字节字符集 ,比如EUC(扩展 Unix 编码 Extended Unix Code)、UTF-8 和 Mule 内部编码。所有被支持的字符集都可以被客户端透明地使用,但少数只能在服务器上使用(即作为一种服务器方编码)。默认的字符集是在使用 initdb
初始化你的PostgreSQL数据库集簇时选择的。在你创建一个数据库时可以重载它,因此你可能会有多个数据库并且每一个使用不同的字符集。
但是,一个重要的限制是每个数据库的字符集必须和数据库的LC_CTYPE
(字符分类)和LC_COLLATE
(字符串排序顺序)设置兼容。对于
C
或POSIX
环境,任何字符集都是允许的,
但是对于其他libc提供的环境只有一种字符集可以正确工作(不过,
在Windows上UTF-8编码可以和任何环境配合使用)。
如果您配置了ICU支持,则ICU提供的区域设置可用于大多数服务器端编码,
但不能用于所有服务器端编码。
表 23.1显示了PostgreSQL中可用的字符集。
表 23.1. PostgreSQL字符集
名称 | 描述 | 语言 | 是否服务器端? | ICU? | 字节/字符 | 别名 |
---|---|---|---|---|---|---|
BIG5 | Big Five | 繁体中文 | 否 | 否 | 1-2 | WIN950 , Windows950 |
EUC_CN | 扩展UNIX编码-中国 | 简体中文 | 是 | 是 | 1-3 | |
EUC_JP | 扩展UNIX编码-日本 | 日文 | 是 | 是 | 1-3 | |
EUC_JIS_2004 | 扩展UNIX编码-日本, JIS X 0213 | 日文 | 是 | 否 | 1-3 | |
EUC_KR | 扩展UNIX编码-韩国 | 韩文 | 是 | 是 | 1-3 | |
EUC_TW | 扩展UNIX编码-台湾 | 繁体中文,台湾话 | 是 | 是 | 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内部编码 | 多语种编辑器 | 是 | 否 | 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-bit | 所有 | 是 | 是 | 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
,服务器把字节值0-127根据 ASCII标准解释,而字节值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
将创建一个使用EUC_KR
字符集和ko_KR
区域的名为korean
的数据库。 另外一种实现方法是使用 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
并不强制存储在数据库中的数据具有任何特定的编码,并且这样这种选择存在着区域依赖的不正当行为的风险。使用这种设置组合的做法已经被废弃,并且在某天将被完全禁止。
PostgreSQL支持一些编码在服务器和前端之间的自动编码转换。转换信息在系统目录pg_conversion
中存储。PostgreSQL带着一些预定义的转换,如表 23.2所示。你可以使用SQL命令CREATE CONVERSION
创建一个新的转换。
表 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 to 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(见第 33.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联盟的网站。
UTF-8 (8-bit UCS/Unicode转换格式)在这里定义。