9.3 9.4 9.5 9.6 10 11 12 13 14 15 Current(16) 17
问题报告 纠错本页面

24.1. 区域支持 #

24.1.1. 概述
24.1.2. 行为
24.1.3. 选择区域设置
24.1.4. 区域设置提供程序
24.1.5. ICU 区域设置
24.1.6. 问题

区域支持指的是应用遵守文化偏好的问题,包括字母表、排序、数字格式等。PostgreSQL使用服务器操作系统提供的标准 ISO C 和POSIX的区域机制。更多的信息请参考你的系统的文档。

24.1.1. 概述 #

区域支持是在使用initdb创建一个数据库集簇时自动被初始化的。默认情况下,initdb将会按照它的执行环境的区域设置初始化数据库集簇; 因此如果你的系统已经设置为你的数据库集簇想要使用的区域, 那么你就没有什么可干的。如果你想使用其它的区域(或者你还不知道你的系统设置的区域是什么),那么你可以用--locale选项准确地告诉initdb你要用哪一个区域。 比如:

initdb --locale=sv_SE

这个Unix系统上的例子把区域设置为瑞典(SE)瑞典语(sv)。 其他的可能性包括 en_US(美国英语)和fr_CA(加拿大法语)。如果有多于一种字符集可以用于区域,那么声明可以采用如下的形式:language_territory.codeset。例如fr_BE.UTF-8表示在比利时(BE)讲的法语(fr),使用一个UTF-8字符集编码。

在你的系统上有哪些区域可用取决于操作系统提供商提供了什么以及安装了什么。在大部分Unix系统上,命令locale -a将会提供一个所有可用区域的列表。Windows使用一些更繁琐的区域名,例如German_Germany或者Swedish_Sweden.1252,但是其原则是相同的。

有时候,把几种区域规则混合起来也很有用,比如,使用英语排序规则而用西班牙语消息。 为了支持这些,我们有一套区域子类用于控制本地化规则的某些方面:

LC_COLLATE字符串排序顺序
LC_CTYPE字符分类(什么是一个字符?它的大写形式是否等效?)
LC_MESSAGES消息使用的语言Language of messages
LC_MONETARY货币数量使用的格式
LC_NUMERIC数字的格式
LC_TIME日期和时间的格式

这些类名转换成initdb的选项名来覆盖某个特定分类的区域选择。比如,要把区域设置为加拿大法语,但使用 U.S. 规则格式化货币,可以使用initdb --locale=fr_CA --lc-monetary=en_US

如果你想让系统表现得象没有区域支持,那么使用特殊的区域名C或者等效的POSIX

一些区域分类的值必需在数据库被创建时的就被固定。你可以为不同的数据库使用不同的设置,但是一旦一个数据库被创建,你就不能在数据库上修改这些区域分类的值。LC_COLLATELC_CTYPE就是这样的分类。它们影响索引的排序顺序,因此它们必需保持固定, 否则在文本列上的索引将会崩溃(但是你可以使用排序规则放松这种限制,讨论见第 24.2 节)。这些分类的默认值在initdb运行时被确定,并且这些值在新数据库被创建时使用,除非在CREATE DATABASE命令中特别指定。

其它区域分类可以在任何时候被更改,更改的方式是设置与区域分类同名的服务器配置参数(详见第 20.11.2 节)。被initdb选中的值实际上只是被写入到配置文件postgresql.conf中作为服务器启动时的默认值。如果你将这些赋值从postgresql.conf中除去,那么服务器将会从其执行环境中继承该设置。

请注意服务器的区域行为是由它看到的环境变量决定的,而不是由任何客户端的环境变量影响的。 因此,我们要在启动服务器之前认真地设置好这些变量。这样带来的一种后果是如果客户端和服务器设置成不同的区域, 那么消息可能以不同的语言呈现,实际情况取决于它们的起源地。

注意

在我们谈到从执行环境继承区域的时候,我们的意思是在大多数操作系统上的下列动作: 对于一个给定的区域分类,比如排序规则,按照下面的顺序评估这些环境变量, 直到找到一个被设置了的:LC_ALLLC_COLLATE(或者对应于相应分类的变量)、LANG。如果这些环境变量一个都没有被设置,那么将区域缺省设置为C

一些消息本地化库也查看环境变量LANGUAGE,它覆盖所有其它用于设置消息语言的区域设置。如果有疑问, 请参考你的操作系统的文档,特别是有关gettext的文档。

要允许消息被翻译成用户喜欢的语言,编译时必需打开NLSconfigure --enable-nls)。所有其他区域支持都会被自动编译。

24.1.2. 行为 #

区域设置特别影响下面的 SQL 特性:

  • 在文本数据上使用ORDER BY或标准比较操作符的查询中的排序顺序

  • 函数upperlowerinitcap

  • 模式匹配操作符(LIKESIMILAR TO和POSIX风格的正则表达式);区域影响大小写不敏感匹配和通过字符类正则表达式的字符分类

  • to_char函数家族

  • LIKE子句使用索引的能力

PostgreSQL中使用非C或非POSIX区域的缺点是性能影响。它降低了字符处理的速度并且阻止了在LIKE中对普通索引的使用。因此,只能在真正需要的时候才使用它。

作为允许PostgreSQL在非 C 区域下为LIKE子句使用索引, 有好几种自定义操作符类可用。这些操作符类允许创建一个执行严格按字符比较的索引。详见第 11.10 节。另一种方法是创建使用C排序规则的索引,如第 24.2 节所讨论的。

24.1.3. 选择区域设置 #

区域设置可以根据需求在不同范围内进行选择。 上述概述展示了如何使用initdb指定区域设置, 以设置整个集群的默认值。以下列表显示了可以选择区域设置的位置。 每个项目提供了后续项目的默认值,每个较低项目允许在更细粒度上覆盖默认值。

  1. 如上所述,操作系统的环境为新初始化的数据库集群的区域设置提供了默认值。 在许多情况下,这已经足够了:如果操作系统配置为所需的语言/地区, 那么PostgreSQL默认也会按照该区域设置行为。

  2. 如上所示,initdb的命令行选项指定了新初始化的集簇的区域设置。 如果操作系统没有您想要的数据库系统的区域设置配置,请使用此选项。

  3. 每个数据库可以单独选择一个区域设置。SQL命令CREATE DATABASE及其命令行等效命令createdb都有相应的选项。例如,如果集簇中包含多个租户的数据库,且这些租户有不同的需求,则可以使用此功能。

  4. 可以为单独的表列设置区域设置。这使用了一个名为collation的SQL对象, 并在第 24.2 节中进行了解释。例如,可以使用此功能对不同语言的数据进行排序, 或自定义特定表的排序顺序。

  5. 最后,可以为单个查询选择区域设置。同样,这使用SQL排序对象。这可以用于根据运行时选择更改排序顺序或进行临时实验。

24.1.4. 区域设置提供程序 #

PostgreSQL支持多个locale providers。 这指定了哪个库提供了locale数据。一个标准的提供程序名称是libc, 它使用操作系统C库提供的locales。这些是大多数操作系统提供的工具使用的locales。 另一个提供程序是icu,它使用外部ICU库。 只有在构建PostgreSQL时配置了对ICU的支持才能使用ICU locales。

选择区域设置的命令和工具,如上所述,每个都有一个选项来选择区域提供程序。之前显示的示例都使用默认的libc提供程序。这里有一个使用ICU提供程序初始化集簇的示例:

initdb --locale-provider=icu --icu-locale=en

有关各个命令和程序的详细信息,请参阅其描述。请注意,您可以在不同的粒度上混合使用区域提供程序,例如默认情况下为集群使用libc,但有一个数据库使用icu提供程序,然后在这些数据库中使用任一提供程序的排序对象。

使用哪个区域设置提供程序取决于个人需求。对于大多数基本用途,任何一个提供程序都会提供足够的结果。 对于libc提供程序,取决于操作系统提供了什么;一些操作系统比其他操作系统更好。 对于高级用途,ICU提供更多的区域设置变体和定制选项。

24.1.5. ICU 区域设置 #

24.1.5.1. ICU 区域名称 #

ICU 格式的区域名称是一个语言标签

CREATE COLLATION mycollation1 (provider = icu, locale = 'ja-JP');
CREATE COLLATION mycollation2 (provider = icu, locale = 'fr');

24.1.5.2. 区域设置规范化和验证 #

在定义一个新的ICU排序对象或使用ICU作为提供者的数据库时,如果给定的区域设置名称 尚未采用语言标签的形式,它将被转换(“规范化”)为语言标签。例如,

CREATE COLLATION mycollation3 (provider = icu, locale = 'en-US-u-kn-true');
NOTICE:  使用区域设置 "en-US-u-kn-true" 的标准形式 "en-US-u-kn"
CREATE COLLATION mycollation4 (provider = icu, locale = 'de_DE.utf8');
NOTICE:  使用区域设置 "de_DE.utf8" 的标准形式 "de-DE"

如果您看到此通知,请确保providerlocale 是预期的结果。为了在使用ICU提供者时获得一致的结果,请指定规范的语言标签,而不是依赖于转换。

一个没有语言名称的区域设置,或者特殊的语言名称 root,会被转换为具有语言 und(“未定义”)的形式。

ICU 可以将大多数 libc 区域设置名称以及某些其他格式转换为语言标签, 以便更轻松地过渡到 ICU。如果在 ICU 中使用 libc 区域设置名称, 它的行为可能与 libc 中的行为不完全相同。

如果在解释区域设置名称时出现问题,或者如果区域设置名称表示 ICU无法识别的语言或地区,您将看到以下警告:

CREATE COLLATION nonsense (provider = icu, locale = 'nonsense');
WARNING:  ICU locale "nonsense" has unknown language "nonsense"
HINT:  To disable ICU locale validation, set parameter icu_validation_level to DISABLED.
CREATE COLLATION

icu_validation_level 控制消息的报告方式。 除非设置为 ERROR,否则排序规则仍将被创建, 但其行为可能不是用户所期望的。

24.1.5.3. 语言标签 #

BCP 47中定义的语言标签是一种标准化的标识符,用于标识语言、 地区以及有关区域的其他信息。

基本语言标签只是 语言-地区; 或者甚至只是语言。其中 语言是一个语言代码 (例如fr表示法语),而 地区是一个地区代码 (例如CA表示加拿大)。示例: ja-JPdefr-CA

排序设置可以包含在语言标签中,以自定义排序行为。ICU允许广泛的 自定义,例如对重音符号、大小写和标点符号的敏感性(或不敏感性); 文本中数字的处理;以及许多其他选项,以满足各种用途的需求。

要在语言标签中包含此附加的排序信息,请附加-u,表示 存在额外的排序设置,然后后接一个或多个 -- 对。是一个 排序设置的键, 而是该设置的有效值。对于布尔设置, -可以在没有对应的 -的情况下指定,这意味着 值为true

例如,语言标签en-US-u-kn-ks-level2 表示使用英语语言的美国地区的区域设置,其中排序设置 kn被设置为true,而ks 被设置为level2。这些设置意味着排序将对大小写不敏感, 并将一系列数字视为一个单一的数字:

CREATE COLLATION mycollation5 (provider = icu, deterministic = false, locale = 'en-US-u-kn-ks-level2');
SELECT 'aB' = 'Ab' COLLATE mycollation5 as result;
 result
--------
 t
(1 row)

SELECT 'N-45' < 'N-123' COLLATE mycollation5 as result;
 result
--------
 t
(1 row)

请参阅第 24.2.3 节以获取有关使用带有自定义排序信息 的语言标签的详细信息和其他示例。

24.1.6. 问题 #

如果根据上面解释区域支持仍然不能运转,检查一下操作系统的区域支持是否被正确配置。 要检查系统中安装了哪些区域,你可以使用命令locale -a(如果你的操作系统提供了该命令)。

请检查PostgreSQL确实正在使用你认为它该用的区域设置。LC_COLLATELC_CTYPE设置都是在数据库创建时决定的,并且在除了创建数据库之外的操作中都不能被更改。其它的区域设置包括LC_MESSAGESLC_MONETARY都是由服务器启动的环境决定的, 但是可以在运行时修改。你可以用SHOW命令检查活跃的区域设置。

源代码目录的src/test/locale中包含PostgreSQL的区域支持的测试套件。

那些通过分析错误消息来处理服务器端错误的客户端应用很明显会有问题,因为服务器来的消息可能会是以不同语言表示的。 我们建议这类应用的开发人员改用错误代码机制。

维护消息翻译目录需要许多志愿者的坚持不懈的努力, 他们希望PostgreSQL以他们的语言说话。 如果以你的语言表示的消息目前还不可用或者没有完全翻译完成,那么我们很感谢你的协助。如果你想帮忙,那么请参考第 57 章或者向开发者邮递列表发邮件。