文档中心MogDBMogDB StackUqbar
v3.1

文档:v3.1

支持的版本:

其他版本:

排序规则支持

排序规则特性允许为每一列数据或者每个操作指定排序顺序和字符分类行为。 这缓解了LC_COLLATELC_CTYPE在数据库创建后不能被修改的限制。

概念

从概念上讲,collatable数据类型的每个表达式都有一个排序规则。 (内置collatable数据类型有text, varchar以及char。 用户定义的基本类型,也可以标记为可排序的, 当然一个可排序的数据类型的域也是可排序的)。 如果表达式是一个列引用,该表达式的排序规则是就这个列的排序规则。 如果表达式是一个常数,排序规则是常数数据类型的缺省排序规则。 一个更复杂表达式的排序规则从它的输入端排序规则推导,如下所述。

一个表达式的排序规则可以是"默认"排序规则, 它表示数据库的区域设置。一个表达式的排序规则也可能是不确定的。在这种情况下,排序操作和其他需要知道排序规则的操作会失败。

当数据库系统必须执行排序或字符分类时,它使用输入表达式的排序规则。 这会在使用例如ORDER BY子句以及函数或操作符调用(如<)时发生。 应用到ORDER BY子句中的排序规则直接就是排序关键字的排序规则。 应用到函数或操作符调用的排序规则要从参数上派生, 如下文所述。除比较操作符之外,在大小写字母之间转换的函数会考虑排序规则,例如lowerupperinitcap。模式匹配操作符和to_char及相关函数也会考虑排序规则。

对于一个函数或操作符调用, 其排序规则通过检查在执行指定操作时参数的排序规则来获得。 如果该函数或操作符调用的结果是一种可排序的数据类型,万一有外围表达式要求函数或操作符表达式的排序规则,在解析时结果的排序规则也会被用作函数或操作符表达式的排序规则。

一个表达式的排序规则派生可以是显式或隐式。该区别会影响多个不同的排序规则出现在同一个表达式中时如何组合它们。当使用一个COLLATE子句时,将发生显式排序规则派生。所有其他排序规则派生都是隐式的。当多个排序规则需要被组合时(例如在一个函数调用中),将使用下面的规则:

  1. 如果任何一个输入表达式具有一个显式排序规则派生,则在输入表达式之间的所有显式派生的排序规则必须相同,否则将产生一个错误。如果任何一个显式派生的排序规则存在,它就是排序规则组合的结果。
  2. 否则,所有输入表达式必须具有相同的隐式排序规则派生或默认排序规则。如果任何一个非默认排序规则存在,它就是排序规则组合的结果。否则,结果是默认排序规则。
  3. 如果在输入表达式之间存在冲突的非默认隐式排序规则,则组合被认为是具有不确定排序规则。这并非一种错误情况,除非被调用的特定函数要求提供排序规则。 如果是这样,在运行时将引发一个错误。

例如,创建下表:

CREATE TABLE test1 (
    a text COLLATE "de_DE",
    b text COLLATE "es_ES",
    ...
);

然后

SELECT a < 'foo' FROM test1;

按照de_DE规则,执行<比较,因为表达式包含隐式推导排序规则与缺省排序规则,但是

SELECT a < ('foo' COLLATE "fr_FR") FROM test1;

使用fr_FR规则执行比较时,因为显式排序规则覆盖了隐式的。 此外,

SELECT a < b FROM test1;

解析器无法确定应该应用哪个排序规则,因为 a列和b列拥有冲突的隐式排序规则。 因为<操作符确实需要知道所使用的排序规则,这将导致一个错误。 该错误可以通过在一个输入表达式上附加一个显式排序规则说明符来解决,因此:

SELECT a < b COLLATE "de_DE" FROM test1;

或者

SELECT a COLLATE "de_DE" < b FROM test1;

另一方面,结构上类似的情况

SELECT a || b FROM test1;

不会产生错误,因为||操作符并不关心排序规则: 不论什么排序规则结果都是一样的。

如果函数或者操作符的结果还是可排序的数据类型, 那么分配给函数或者操作符的组合的输入表达式的排序规则也会应用到函数或者操作符结果上。 因此,

SELECT * FROM test1 ORDER BY a || 'foo';

按照de_DE规则执行该排序。但是这个查询:

SELECT * FROM test1 ORDER BY a || b;

导致一个错误,因为即使||操作符不需要知道排序规则,而ORDER BY子句 确实需要。和前面一样,可以使用显式的排序规则说明符解决这个冲突。

SELECT * FROM test1 ORDER BY a || b COLLATE "fr_FR";

管理排序规则

排序规则是把SQL名称映射到操作系统区域的SQL模式对象。排序规则定义中有一个提供程序, 它指定哪个库提供语言环境数据。一个标准提供程序名称是libc, 它使用操作系统C库提供的语言环境。这些是操作系统提供的大多数工具使用的语言环境。 另一个提供程序是icu,它使用外部ICU库。 只有在构建MogDB时配置了对ICU的支持,才能使用ICU区域设置。

libc提供的一个排序规则对象映射到LC_COLLATELC_CTYPE的组合, 如setlocale()系统库调用一样。 (顾名思义,排序规则的主要目的是设置LC_COLLATE, 它控制排序顺序。但在实际中很少需要一个和 LC_COLLATE不同的LC_CTYPE设置, 因此通过一个概念来收集这些信息比为了设置每一个表达式的 LC_CTYPE而创建另一种架构要更加方便)。此外,libc排序规则和字符集编码(见字符集支持) 紧密关联。 对不同的编码可能存在同名的排序规则。

icu提供的排序规则对象映射到由ICU库提供的指定整理器。 ICU不支持单独的“collate”和“ctype”设置, 所以它们总是相同的。此外,ICU排序规则与编码无关, 因此在数据库中总是只有一个给定名称的ICU排序规则。

标准的排序规则

在所有平台上,名称为default, CPOSIX排序规则都是可用的。其他可用的排序规则取决于操作系统支持。default排序规则选择在创建数据库时指定的LC_COLLATELC_CTYPE值。 CPOSIX的排序规则都表现为"传统 C"的行为, 即只有ASCII字母"A"到"Z" 被视为字母,并且严格按照字符的编码字节值进行排序。

此外,SQL标准排序规则名称ucs_basic可用于编码UTF8。 它相当于C,并按Unicode代码点排序。

预定义的排序规则

如果操作系统提供了在一个程序中使用多语言环境的支持 (newlocale以及相关函数),那么当一个数据库集群初始化的时候, gs_initdb使用基于当时在操作系统上发现的所有语言环境的排序规则来填充系统表pg_collation

要检查当前可用的语言环境,请在gsql中使用查询 SELECT * FROM pg_collation或命令\dOS +

libc 排序规则

例如,操作系统可能提供名为de_DE.utf8的区域。 那么,gs_initdb就可能为编码UTF8创建命名为 de_DE.utf8的排序规则,它的LC_COLLATELC_CTYPE都被设置为de_DE.utf8。 它还将创建名称中被剥离了.utf8标签的排序规则。 所以,也可以使用de_DE名称的排序规则 ,这方便于编写并且使得名称较少依赖于编码。然而,需要注意的是, 排序规则名称的初始设置是平台相关的。

libc提供的默认排序规则直接映射到操作系统中安装的语言环境, 可以使用命令locale -a列出。

在任何特定的数据库中,只关心使用该数据库编码的排序规则。pg_collation中的其他项会被忽略。因此,剥离了编码名的排序规则名称,如de_DE,在一个给定的数据库中也算是独一无二的,即使它不是全局唯一的。 建议使用剥离过的排序规则名称,因为如果以后决定改变到另一个数据库编码,可以少改一样东西。 但是请注意,无论是什么数据库编码,都可以使用default, CPOSIX排序规则。

MogDB认为不同排序规则对象是不兼容的,即使他们有相同的属性。 例如:

SELECT a COLLATE "C" < b COLLATE "POSIX" FROM test1;

将引起一个错误,即使CPOSIX 排序规则具有完全相同的行为。因此不推荐混合剥离的和非剥离的排序规则名。

Copyright © 2011-2024 www.enmotech.com All rights reserved.