字符集支持

PostgreSQL 9.4.4 中文手册
上一页 | 上一级 | 章 22. 区域 | 下一页

# 22.3. 字符集支持

PostgreSQL中的字符集支持可以让你以各种字符集存储文本（也称为编码）， 包含单字节字符集，比如ISO-8859系列和多字节字符集比如EUC(扩展Unix编码)、 UTF-8、Mule国际编码。 所有字符集都可以被客户端透明地使用。 但是有一些不支持在服务器上使用（即作为服务器端编码）。 缺省的字符集是在使用`initdb`初始化数据库集群的时候选择的。 在你创建数据库的时候是可以覆盖这个缺省值的。因此，你可以有多个数据库， 每个都有不同的字符集。

但是，有一个重要的限制，每个数据库的字符集必须与该数据库的`LC_CTYPE`（字符类别）以及 `LC_COLLATE`（字符串排序顺序）区域设置相兼容。对于`C`或者 `POSIX`区域，允许任何字符集， 但对于其他区域只有一个字符集设置能正常工作。（不过在Windows上，UTF-8编码可用于任何区域）。

## 22.3.1. 支持的字符集

表 22-1显示了可以在PostgreSQL中使用的 字符集。

表 22-1. PostgreSQL字符集

名字 | 描述 | 语言 | 服务端? | 字节数/字符 | 别名
--- | --- | --- | --- | --- | ---
`BIG5` | 大五码 | 繁体中文 | No | 1-2 | `WIN950`, `Windows950`
`EUC_CN` | 扩展UNIX代码-CN | 简体中文 | Yes | 1-3 |
`EUC_JP` | 扩展UNIX代码-JP | 日文 | Yes | 1-3 |
`EUC_JIS_2004` | 扩展UNIX代码-JP, JIS X 0213 | 日文 | Yes | 1-3 |
`EUC_KR` | 扩展UNIX代码-KR | 韩文 | Yes | 1-3 |
`EUC_TW` | 扩展UNIX代码-TW | 繁体中文，台湾 | Yes | 1-3 |
`GB18030` | 国标码 | 中文 | No | 1-2 |
`GBK` | 扩展国标码 | 简体中文 | No | 1-2 | `WIN936`, `Windows936`
`ISO_8859_5` | ISO 8859-5, ECMA 113 | 拉丁/西里尔语 | Yes | 1 |
`ISO_8859_6` | ISO 8859-6, ECMA 114 | 拉丁/阿拉伯语 | Yes | 1 |
`ISO_8859_7` | ISO 8859-7, ECMA 118 | 拉丁/希腊语 | Yes | 1 |
`ISO_8859_8` | ISO 8859-8, ECMA 121 | 拉丁/希伯莱语 | Yes | 1 |
`JOHAB` | JOHAB | 韩语 | No | 1-3 |
`KOI8R` | KOI8-R | 西里尔语(俄国) | Yes | 1 | `KOI8`
`KOI8U` | KOI8-U | 西里尔语(乌克兰) | Yes | 1 |
`LATIN1` | ISO 8859-1, ECMA 94 | 西欧语 | Yes | 1 | `ISO88591`
`LATIN2` | ISO 8859-2, ECMA 94 | 中欧语 | Yes | 1 | `ISO88592`
`LATIN3` | ISO 8859-3, ECMA 94 | 南欧语 | Yes | 1 | `ISO88593`
`LATIN4` | ISO 8859-4, ECMA 94 | 北欧语 | Yes | 1 | `ISO88594`
`LATIN5` | ISO 8859-9, ECMA 128 | 土耳其语 | Yes | 1 | `ISO88599`
`LATIN6` | ISO 8859-10, ECMA 144 | 日耳曼语 | Yes | 1 | `ISO885910`
`LATIN7` | ISO 8859-13 | 波罗的海语 | Yes | 1 | `ISO885913`
`LATIN8` | ISO 8859-14 | 凯尔特语 | Yes | 1 | `ISO885914`
`LATIN9` | ISO 8859-15 | 带有欧洲语系和语调的LATIN1 | Yes | 1 | `ISO885915`
`LATIN10` | ISO 8859-16, ASRO SR 14111 | 罗马尼亚语 | Yes | 1 | `ISO885916`
`MULE_INTERNAL` | Mule internal code | 多语种Emacs | Yes | 1-4 |
`SJIS` | Shift JIS | 日语 | No | 1-2 | `Mskanji`, `ShiftJIS`, `WIN932`, `Windows932`
`SHIFT_JIS_2004` | Shift JIS, JIS X 0213 | 日语 | No | 1-2 |
`SQL_ASCII` | unspecified (see text) | 任意 | Yes | 1 |
`UHC` | Unified Hangul Code | 韩语 | No | 1-2 | `WIN949`, `Windows949`
`UTF8` | Unicode, 8-bit | 全部 | Yes | 1-4 | `Unicode`
`WIN866` | Windows CP866 | 西里尔语 | Yes | 1 | `ALT`
`WIN874` | Windows CP874 | 泰国语 | Yes | 1 |
`WIN1250` | Windows CP1250 | 中欧语 | Yes | 1 |
`WIN1251` | Windows CP1251 | 西里尔语 | Yes | 1 | `WIN`
`WIN1252` | Windows CP1252 | 西欧语 | Yes | 1 |
`WIN1253` | Windows CP1253 | 希腊语 | Yes | 1 |
`WIN1254` | Windows CP1254 | 土耳其语 | Yes | 1 |
`WIN1255` | Windows CP1255 | 希伯来语 | Yes | 1 |
`WIN1256` | Windows CP1256 | 阿拉伯语 | Yes | 1 |
`WIN1257` | Windows CP1257 | 波罗的语 | Yes | 1 |
`WIN1258` | Windows CP1258 | 越南语 | Yes | 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字符。

## 22.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

将创建一个使用`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`数据库。当拷贝任何其他数据库时， 来自源数据库的编码和区域设置不能被改变，因为可能导致数据损坏。参阅第 21.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`不强制存储在数据库中的数据 具有任何特定的编码，所以这个选择带来 区域相关的不当行为的风险。使用这样的设置组合是不推荐的，也许有一天会被完全禁止。

## 22.3.3. 服务器和客户端之间的自动字符集转换

PostgreSQL支持在服务器和前端之间的自动编码转换。 转换信息在系统表`pg_conversion`中存储。 PostgreSQL带着一些预定义的转换。 它们在表 22-2中列出。 你可以使用SQL命令`CREATE CONVERSION`创建一个新的转换。

表 22-2. 客户/服务器字符集转换

服务器字符集 | 可用客户端字符集
--- | ---
`BIG5` | 不支持做服务器端编码
`EUC_CN` | EUC_CN, `MULE_INTERNAL`, `UTF8`
`EUC_JP` | EUC_JP, `MULE_INTERNAL`, `SJIS`, `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` | JOHAB, `UTF8`
`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` | 不支持做服务器端编码
`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 (第 31.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`是不明智的。

## 22.3.4. 进一步阅读

下面是学习各种类型的编码系统的好地方。

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转换格式)的定义。

上一页 | 起始页 | 下一页
排序规则支持 | 上一级 | 日常数据库维护工作