💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 22.3\. 字符集支持 PostgreSQL中的字符集支持可以让你以各种字符集存储文本(也称为编码), 包含单字节字符集,比如ISO-8859系列和多字节字符集比如EUC(扩展Unix编码)、 UTF-8、Mule国际编码。 所有字符集都可以被客户端透明地使用。 但是有一些不支持在服务器上使用(即作为服务器端编码)。 缺省的字符集是在使用`initdb`初始化数据库集群的时候选择的。 在你创建数据库的时候是可以覆盖这个缺省值的。因此,你可以有多个数据库, 每个都有不同的字符集。 但是,有一个重要的限制,每个数据库的字符集必须与该数据库的`LC_CTYPE`(字符类别)以及 `LC_COLLATE`(字符串排序顺序)区域设置相兼容。对于`C`或者 `POSIX`区域,允许任何字符集, 但对于其他区域只有一个字符集设置能正常工作。(不过在Windows上,UTF-8编码可用于任何区域)。 ## 22.3.1\. 支持的字符集 [Table 22-1](#calibre_link-1614)显示了可以在PostgreSQL中使用的 字符集。 **Table 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`数据库。当拷贝任何其他数据库时, 来自源数据库的编码和区域设置不能被改变,因为可能导致数据损坏。参阅[Section 21.3](#calibre_link-1266) 获取更多信息。 数据库的编码是存储在`pg_database`系统表中的。 你可以用`psql`的`-l`选项或`\l` 命令列出这些编码。 ``` $ <kbd class="literal">psql -l</kbd> 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) ``` > **Important:** 在大多数现代操作系统中,PostgreSQL可以通过 `LC_CTYPE`的设置决定使用哪种字符集,并且强制只使用匹配的数据库编码。在旧的操作系统上 你有责任确保使用所选区域所期望的编码。 如果这上面犯错误很可能导致与区域相关的操作表现出古怪的行为,比如排序。 > > 即使当`LC_CTYPE`不是`C`或者`POSIX`时, PostgreSQL也允许超级用户创建 使用`SQL_ASCII`编码的数据库。正如 以上所述,`SQL_ASCII`不强制存储在数据库中的数据 具有任何特定的编码,所以这个选择带来 区域相关的不当行为的风险。使用这样的设置组合是不推荐的,也许有一天会被完全禁止。 ## 22.3.3\. 服务器和客户端之间的自动字符集转换 PostgreSQL支持在服务器和前端之间的自动编码转换。 转换信息在系统表`pg_conversion`中存储。 PostgreSQL带着一些预定义的转换。 它们在[Table 22-2](#calibre_link-1615)中列出。 你可以使用SQL命令`CREATE CONVERSION`创建一个新的转换。 **Table 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 ([Section 31.10](#calibre_link-776))函数控制客户端编码。 * 使用`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](#calibre_link-1030)配置变量。 如果在`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/](http://www.unicode.org/) Unicode主页。 RFC 3629 UTF-8 (8-bit UCS/Unicode转换格式)的定义。