9.3 9.4 9.5 9.6 10 11 12 13 14 15
阿里云PostgreSQL 问题报告 纠错本页面

24.1. 区域支持

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

区域支持指的是应用遵守文化偏好的问题,包括字母表、排序、数字格式等。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提供程序。 这指定了哪个库提供了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. 问题

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

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

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

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

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