受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: 19 / devel
此文档适用于不受支持的 PostgreSQL 版本。
您可能需要查看当前版本的相同页面,或上面列出的其他受支持版本。

23.3. 字符集支持 #

PostgreSQL中的字符集支持允许你以多种字符集 (也称为编码)存储文本,包括 ISO 8859 系列之类的单字节字符集,以及 EUC(扩展 Unix 编码)和 UTF-8 等多字节字符集。所有 受支持的字符集都可以被客户端透明地使用,但其中少 数不支持在服务器内部使用(即不能作为服务器端编码)。默认字符集是在使用 initdb初始化PostgreSQL 数据库集簇时选定的。创建数据库时可以覆盖该设置,因此你可以拥有多个数据 库,并让每个数据库使用不同的字符集。

不过,一个重要限制是,每个数据库的字符集必须与该数据库的 LC_CTYPE(字符分类)和LC_COLLATE(字符串 排序顺序)区域设置兼容。对于CPOSIX 区域设置,任何字符集都可以使用;但对于其他由 libc 提供的区域设置,通常 只有一种字符集能够正确工作。(不过在 Windows 上,UTF-8 编码可以与任何区域设置配合使用。)如果配置了 ICU 支持,则 ICU 提供的区 域设置可用于大多数(但不是全部)服务器端编码。

23.3.1. 支持的字符集 #

Table 23.3显示了PostgreSQL中可用的字符集。

Table 23.3. PostgreSQL 字符集

名称 描述 语言 是否服务器端? ICU? 字节/​字符 别名
BIG5 Big Five 繁体中文 1–2 WIN950, Windows950
EUC_CN 扩展 Unix 编码-CN 简体中文 1–3  
EUC_JP 扩展 Unix 编码-JP 日语 1–3  
EUC_JIS_2004 扩展 Unix 编码-JP,JIS X 0213 日语 1–3  
EUC_KR 扩展 Unix 编码-KR 韩语 1–3  
EUC_TW 扩展 Unix 编码-TW 繁体中文、台湾语 1–4  
GB18030 国家标准,2022 版 中文 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
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 位 所有 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 驱动就不支持 LATIN6LATIN8LATIN10

SQL_ASCII的行为与其他设置有很大不同。当服务器字符 集为SQL_ASCII时,服务器会按 ASCII 标准解释字节值 0–127,而将字节值 128–255 视为未解释字符。设置为 SQL_ASCII时不会执行编码转换。因此,这一设置与其说 是声明正在使用某种特定编码,不如说是承认自己并不知道编码是什么。在大 多数情况下,如果要处理任何非 ASCII 数据,使用SQL_ASCII 都是不明智的,因为PostgreSQL无法帮助你 转换或校验非 ASCII 字符。

23.3.2. 设置字符集 #

initdbPostgreSQL集 簇定义默认字符集(编码)。例如:

initdb -E EUC_JP

这会把默认字符集设为EUC_JP(日语的扩展 Unix 编 码)。如果你喜欢更长的选项形式,也可以用--encoding代 替-E。如果既没有给出-E也没有给出 --encodinginitdb会根据指定的 或默认的区域设置,尝试确定应使用的合适编码。

你可以在创建数据库时指定非默认编码,只要该编码与所选区域设置兼容:

createdb -E EUC_KR -T template0 --lc-collate=ko_KR.euckr --lc-ctype=ko_KR.euckr korean

这将创建一个名为korean的数据库,它使用 EUC_KR字符集和ko_KR区域设置。 另一种实现方式是使用以下 SQL 命令:

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 命令查看它。

$ 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)

Important

在大多数现代操作系统上,PostgreSQL能够 判断LC_CTYPE设置所隐含的字符集,并强制只允许使用与之 匹配的数据库编码。在较老的系统上,你需要自行确保所用编码正是所选区域 设置期望的编码。这里的错误很可能会导致区域设置相关操作(例如排序)出 现奇怪的行为。

即使LC_CTYPE不是CPOSIXPostgreSQL 仍允许超级用户创建使用SQL_ASCII编码的数据库。正如 前文所述,SQL_ASCII并不强制数据库中存储的数据具 有任何特定编码,因此这种选择存在区域设置相关误行为的风险。这种设置组 合已经被弃用,未来某一天可能会被完全禁止。

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

PostgreSQL支持在许多字符集组合之间自动在 服务器和客户端之间进行字符集转换(哪些组合可用,见Section 23.3.4)。

若要启用自动字符集转换,必须告诉PostgreSQL 你希望客户端使用哪种字符集(编码)。有几种方法可以做到这一点:

  • psql中使用\encoding 命令。\encoding允许动态更改客户端编码。例如,要把 编码改成SJIS,可以输入:

    \encoding SJIS
    
  • libpqSection 32.11) 提供了控制客户端编码的函数。

  • 使用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,那么无论服务 器字符集是什么,编码转换都会被禁用。(但是,如果服务器字符集不是 SQL_ASCII,服务器仍会检查传入数据对该编码是否有 效,因此最终效果相当于客户端字符集与服务器字符集相同。)和服务器端一 样,除非你处理的全部都是 ASCII 数据,否则使用 SQL_ASCII并不明智。

23.3.4. 可用的字符集转换 #

PostgreSQL允许在pg_conversion 系统目录中列出了转换函数的任意两个字符集之间进行转换。 PostgreSQL自带了一些预定义转换,概况见Table 23.4,更详细的信息见Table 23.5。你也可以使用 SQL 命令CREATE CONVERSION创建新的转换。(若要用于自动的客户 端/服务器转换,该字符集对的转换必须被标记为default。)

Table 23.4. 内置客户端/服务器字符集转换

服务器字符集 可用的客户端字符集
BIG5 不支持作为服务器编码
EUC_CN EUC_CN, UTF8
EUC_JP EUC_JP, SJIS, UTF8
EUC_JIS_2004 EUC_JIS_2004, SHIFT_JIS_2004, UTF8
EUC_KR EUC_KR, UTF8
EUC_TW EUC_TW, BIG5, UTF8
GB18030 不支持作为服务器编码
GBK 不支持作为服务器编码
ISO_8859_5 ISO_8859_5, KOI8R, 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, UTF8, WIN866, WIN1251
KOI8U KOI8U, UTF8
LATIN1 LATIN1, UTF8
LATIN2 LATIN2, UTF8, WIN1250
LATIN3 LATIN3, UTF8
LATIN4 LATIN4, UTF8
LATIN5 LATIN5, UTF8
LATIN6 LATIN6, UTF8
LATIN7 LATIN7, UTF8
LATIN8 LATIN8, UTF8
LATIN9 LATIN9, UTF8
LATIN10 LATIN10, UTF8
SJIS 不支持作为服务器编码
SHIFT_JIS_2004 不支持作为服务器编码
SQL_ASCII 任何(不会执行转换)
UHC 不支持作为服务器编码
UTF8 所有受支持的编码
WIN866 WIN866, ISO_8859_5, KOI8R, UTF8, WIN1251
WIN874 WIN874, UTF8
WIN1250 WIN1250, LATIN2, UTF8
WIN1251 WIN1251, ISO_8859_5, KOI8R, UTF8, WIN866
WIN1252 WIN1252, UTF8
WIN1253 WIN1253, UTF8
WIN1254 WIN1254, UTF8
WIN1255 WIN1255, UTF8
WIN1256 WIN1256, UTF8
WIN1257 WIN1257, UTF8
WIN1258 WIN1258, UTF8

Table 23.5. 所有内置字符集转换

转换名称 [a] 源编码 目标编码
big5_to_euc_tw BIG5 EUC_TW
big5_to_utf8 BIG5 UTF8
euc_cn_to_utf8 EUC_CN UTF8
euc_jp_to_sjis EUC_JP SJIS
euc_jp_to_utf8 EUC_JP UTF8
euc_kr_to_utf8 EUC_KR UTF8
euc_tw_to_big5 EUC_TW BIG5
euc_tw_to_utf8 EUC_TW UTF8
gb18030_to_utf8 GB18030 UTF8
gbk_to_utf8 GBK UTF8
iso_8859_10_to_utf8 LATIN6 UTF8
iso_8859_13_to_utf8 LATIN7 UTF8
iso_8859_14_to_utf8 LATIN8 UTF8
iso_8859_15_to_utf8 LATIN9 UTF8
iso_8859_16_to_utf8 LATIN10 UTF8
iso_8859_1_to_utf8 LATIN1 UTF8
iso_8859_2_to_utf8 LATIN2 UTF8
iso_8859_2_to_windows_1250 LATIN2 WIN1250
iso_8859_3_to_utf8 LATIN3 UTF8
iso_8859_4_to_utf8 LATIN4 UTF8
iso_8859_5_to_koi8_r ISO_8859_5 KOI8R
iso_8859_5_to_utf8 ISO_8859_5 UTF8
iso_8859_5_to_windows_1251 ISO_8859_5 WIN1251
iso_8859_5_to_windows_866 ISO_8859_5 WIN866
iso_8859_6_to_utf8 ISO_8859_6 UTF8
iso_8859_7_to_utf8 ISO_8859_7 UTF8
iso_8859_8_to_utf8 ISO_8859_8 UTF8
iso_8859_9_to_utf8 LATIN5 UTF8
johab_to_utf8 JOHAB UTF8
koi8_r_to_iso_8859_5 KOI8R ISO_8859_5
koi8_r_to_utf8 KOI8R UTF8
koi8_r_to_windows_1251 KOI8R WIN1251
koi8_r_to_windows_866 KOI8R WIN866
koi8_u_to_utf8 KOI8U UTF8
sjis_to_euc_jp SJIS EUC_JP
sjis_to_utf8 SJIS UTF8
windows_1258_to_utf8 WIN1258 UTF8
uhc_to_utf8 UHC UTF8
utf8_to_big5 UTF8 BIG5
utf8_to_euc_cn UTF8 EUC_CN
utf8_to_euc_jp UTF8 EUC_JP
utf8_to_euc_kr UTF8 EUC_KR
utf8_to_euc_tw UTF8 EUC_TW
utf8_to_gb18030 UTF8 GB18030
utf8_to_gbk UTF8 GBK
utf8_to_iso_8859_1 UTF8 LATIN1
utf8_to_iso_8859_10 UTF8 LATIN6
utf8_to_iso_8859_13 UTF8 LATIN7
utf8_to_iso_8859_14 UTF8 LATIN8
utf8_to_iso_8859_15 UTF8 LATIN9
utf8_to_iso_8859_16 UTF8 LATIN10
utf8_to_iso_8859_2 UTF8 LATIN2
utf8_to_iso_8859_3 UTF8 LATIN3
utf8_to_iso_8859_4 UTF8 LATIN4
utf8_to_iso_8859_5 UTF8 ISO_8859_5
utf8_to_iso_8859_6 UTF8 ISO_8859_6
utf8_to_iso_8859_7 UTF8 ISO_8859_7
utf8_to_iso_8859_8 UTF8 ISO_8859_8
utf8_to_iso_8859_9 UTF8 LATIN5
utf8_to_johab UTF8 JOHAB
utf8_to_koi8_r UTF8 KOI8R
utf8_to_koi8_u UTF8 KOI8U
utf8_to_sjis UTF8 SJIS
utf8_to_windows_1258 UTF8 WIN1258
utf8_to_uhc UTF8 UHC
utf8_to_windows_1250 UTF8 WIN1250
utf8_to_windows_1251 UTF8 WIN1251
utf8_to_windows_1252 UTF8 WIN1252
utf8_to_windows_1253 UTF8 WIN1253
utf8_to_windows_1254 UTF8 WIN1254
utf8_to_windows_1255 UTF8 WIN1255
utf8_to_windows_1256 UTF8 WIN1256
utf8_to_windows_1257 UTF8 WIN1257
utf8_to_windows_866 UTF8 WIN866
utf8_to_windows_874 UTF8 WIN874
windows_1250_to_iso_8859_2 WIN1250 LATIN2
windows_1250_to_utf8 WIN1250 UTF8
windows_1251_to_iso_8859_5 WIN1251 ISO_8859_5
windows_1251_to_koi8_r WIN1251 KOI8R
windows_1251_to_utf8 WIN1251 UTF8
windows_1251_to_windows_866 WIN1251 WIN866
windows_1252_to_utf8 WIN1252 UTF8
windows_1256_to_utf8 WIN1256 UTF8
windows_866_to_iso_8859_5 WIN866 ISO_8859_5
windows_866_to_koi8_r WIN866 KOI8R
windows_866_to_utf8 WIN866 UTF8
windows_866_to_windows_1251 WIN866 WIN
windows_874_to_utf8 WIN874 UTF8
euc_jis_2004_to_utf8 EUC_JIS_2004 UTF8
utf8_to_euc_jis_2004 UTF8 EUC_JIS_2004
shift_jis_2004_to_utf8 SHIFT_JIS_2004 UTF8
utf8_to_shift_jis_2004 UTF8 SHIFT_JIS_2004
euc_jis_2004_to_shift_jis_2004 EUC_JIS_2004 SHIFT_JIS_2004
shift_jis_2004_to_euc_jis_2004 SHIFT_JIS_2004 EUC_JIS_2004

[a] 转换名称遵循标准命名模式:源编码的正式名称,其中所有非字母数字字符 都替换为下划线,后跟_to_,再跟以相同方式处理 后的目标编码名称。因此,这些名称有时会与Table 23.3 中显示的惯用编码名称不同。


23.3.5. 进一步阅读 #

以下资料是了解各种编码系统的良好起点。

CJKV Information Processing: Chinese, Japanese, Korean & Vietnamese Computing

其中对EUC_JPEUC_CNEUC_KREUC_TW做了详细说明。

https://www.unicode.org/

Unicode Consortium 网站。

RFC 3629

这里定义了UTF-8(8 位 UCS/Unicode 转换格式)。