23.3. 字符集支持
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.3.1. 被支持的字符集
Table 23.1显示了PostgreSQL中可用的字符集。 Table 23.1. PostgreSQL字符集
并非所有的客户端API都支持上面列出的字符集。比如,PostgreSQL的JDBC 驱动就不支持MULE_INTERNAL、LATIN6、LATIN8和LATIN10
。
SQL_ASCII
设置与其他设置表现得相当不同。如果服务器字符集是SQL_ASCII
,服务器把字节值0-127根据 ASCII标准解释,而字节值128-255则当作无法解析的字符。如果设置为SQL_ASCII
,就不会有编码转换。因此,这个设置基本不是用来声明所使用的指定编码,因为这个声明会忽略编码。在大多数情况下,如果你使用了任何非ASCII数据,那么使用SQL_ASCII
设置都是不明智的,因为PostgreSQL将无法帮助你转换或者校验非ASCII字符。
23.3.2. 设置字符集
initdb为一个PostgreSQL集簇定义缺省的字符集(编码)。比如:
代码语言:javascript复制initdb -E EUC_JP
把缺省字符集设置为EUC_JP
(用于日文的扩展Unix 编码)。如果你喜欢用长选项字符串,你可以用–encoding代替-E。 如果没有给出-E或者--encoding
选项,initdb会尝试基于指定的或者默认的区域判断要使用的合适编码。
你可以在数据库创建时指定一个非默认编码,提供的编码应和选择的区域兼容:
代码语言:javascript复制createdb -E EUC_KR -T template0 --lc-collate=ko_KR.euckr --lc-ctype=ko_KR.euckr
korean
将创建一个使用EUC_KR字符集和ko_KR区域的名为korean的数据库。 另外一种实现方法是使用 SQL 命令:
代码语言:javascript复制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命令来查看。
在大部分现代操作系统上,PostgreSQL可以判断LC_CTYPE
设置意味着哪一种字符集,并且它强制只有匹配的数据库编码被使用。在老的系统上你需要自己负责确保所使用的编码就是你所选择的区域所期望的。在这里的一个错误很可能导致区域依赖的操作产生奇怪的行为,例如排序。
即使LC_CTYPE
不是C或POSIX时,PostgreSQL将允许超级用户使用SQL_ASCII
编码创建数据库。正如前文所述,SQL_ASCII
并不强制存储在数据库中的数据具有任何特定的编码,并且这样这种选择存在着区域依赖的不正当行为的风险。
使用这种设置组合的做法已经被废弃,并且在某天将被完全禁止。
23.3.3. 服务器和客户端之间的自动字符集转换
PostgreSQL支持一些编码在服务器和前端之间的自动编码转换。转换信息在系统目录pg_conversion
中存储。PostgreSQL带着一些预定义的转换,如Table 23.2所示。你可以使用SQL命令CREATE CONVERSION创建一个新的转换。
Table 23.2. 客户/服务器字符集转换
要想启用自动字符集转换功能,你必须告诉PostgreSQL你想在客户端使用的字符集(编码)。你可以用好几种方法来完成:
- 用psql里的encoding命令。
encoding
允许你动态修改客户端编码。比如,把编码改变为SJIS,键入:encoding SJIS
- libpq(见Section 34.10)中提供函数控制客户端编码。
- 使用
SET client_encoding TO
。 可以使用这个SQL命令设置客户端编码:
SET CLIENT_ENCODING TO 'value';
你还可以把标准SQL语法里的SET NAMES用于这个目的:
代码语言:javascript复制SET NAMES 'value';
要查询当前客户端编码:
代码语言:javascript复制SHOW client_encoding;
要返回到缺省编码:
代码语言:javascript复制RESET client_encoding;
- 使用PGCLIENTENCODING。如果在客户端的环境里定义了PGCLIENTENCODING环境变量, 那么在与服务器进行了连接后将自动选择客户端编码(这个设置随后可以用上文提到的任何其他方法重载)。
- 使用
client_encoding
配置变量。如果client_encoding
变量被设置, 那么在与服务器建立了连接之后,这个客户端编码将备自动选定(这个设置随后可以用上文提到的其他方法重载)。
假如无法进行一个特定字符的转换 — 假如你选的服务器编码是EUC_JP而 客户端是LATIN1,那么有些日文字符不能转换成LATIN1 — 将会报告一个错误。
如果客户端字符集定义成了SQL_ASCII
,那么编码转换会被禁用, 不管服务器的字符集是什么都一样。和服务器一样,除非你的工作环境全部是 ASCII 数据, 否则使用SQL_ASCII
是不明智的。
23.3.4. 进一步阅读
下面是学习各种类型的编码系统的好资源。
代码语言:javascript复制CJKV Information Processing: Chinese, Japanese, Korean & Vietnamese Computing
包含对EUC_JP、 EUC_CN、EUC_KR、 EUC_TW
的详细解释。
http://www.unicode.org/
Unicode联盟的网站。 RFC 3629 UTF-8 (8-bit UCS/Unicode转换格式)在这里定义。