⌘+k ctrl+k
1.1.3 (stable)
Search Shortcut cmd + k | ctrl + k
Collations

排序规则为执行引擎中的文本排序或比较提供了规则。排序规则对于本地化非常有用,因为不同语言或不同国家的文本排序规则是不同的。这些排序规则通常彼此不兼容。例如,在英语中,字母y位于xz之间。然而,在立陶宛语中,字母y位于ij之间。因此,支持不同的排序规则。用户在执行排序和比较操作时必须选择他们想要使用的排序规则。

默认情况下,使用BINARY排序规则。这意味着字符串仅根据其二进制内容进行排序和比较。这对于标准的ASCII字符(即字母A-Z和数字0-9)是有意义的,但对于特殊的Unicode字符通常没有太大意义。然而,这是迄今为止执行排序和比较的最快方法。因此,除非另有要求,否则建议坚持使用BINARY排序规则。

警告 DuckDB中的排序规则支持有一些已知的限制,并且有几个计划的改进

使用排序规则

在DuckDB的独立安装中,包含了三种排序规则:NOCASENOACCENTNFCNOCASE 排序规则在比较字符时不区分大小写。NOACCENT 排序规则在比较字符时不区分重音符号。NFC 排序规则执行NFC标准化的比较,更多信息请参见Unicode标准化

SELECT 'hello' = 'hElLO';
false
SELECT 'hello' COLLATE NOCASE = 'hElLO';
true
SELECT 'hello' = 'hëllo';
false
SELECT 'hello' COLLATE NOACCENT = 'hëllo';
true

排序规则可以通过使用点运算符链接它们来组合。但是,请注意,并非所有排序规则都可以组合在一起。一般来说,NOCASE 排序规则可以与其他任何排序器组合,但大多数其他排序规则不能组合。

SELECT 'hello' COLLATE NOCASE = 'hElLÖ';
false
SELECT 'hello' COLLATE NOACCENT = 'hElLÖ';
false
SELECT 'hello' COLLATE NOCASE.NOACCENT = 'hElLÖ';
true

默认排序规则

到目前为止,我们所看到的排序规则都是在每个表达式上指定的。也可以在全局数据库级别或基本表列上指定默认的排序器。PRAGMA default_collation 可以用来指定全局默认的排序器。如果没有指定其他排序器,将使用这个排序器。

SET default_collation = NOCASE;
SELECT 'hello' = 'HeLlo';
true

在创建表时,也可以为每列指定排序规则。当该列用于比较时,将使用该列的排序规则来执行比较。

CREATE TABLE names (name VARCHAR COLLATE NOACCENT);
INSERT INTO names VALUES ('hännes');
SELECT name
FROM names
WHERE name = 'hannes';
hännes

然而,在这里要小心,因为不同的排序规则不能混合使用。当你想比较具有不同排序规则的列时,这可能会成为问题。

SELECT name
FROM names
WHERE name = 'hannes' COLLATE NOCASE;
ERROR: Cannot combine types with different collation!
CREATE TABLE other_names (name VARCHAR COLLATE NOCASE);
INSERT INTO other_names VALUES ('HÄNNES');
SELECT names.name AS name, other_names.name AS other_name
FROM names, other_names
WHERE names.name = other_names.name;
ERROR: Cannot combine types with different collation!

我们需要手动覆盖排序规则:

SELECT names.name AS name, other_names.name AS other_name
FROM names, other_names
WHERE names.name COLLATE NOACCENT.NOCASE = other_names.name COLLATE NOACCENT.NOCASE;
名称 其他名称
hännes HÄNNES

ICU 排序规则

我们目前看到的排序规则并不依赖于地区,也不遵循任何特定的地区规则。如果您希望遵循特定地区或语言的规则,您需要使用ICU排序规则之一。为此,您需要加载ICU扩展

如果您使用的是C++ API,您可以在DuckDB项目的extension/icu文件夹中找到扩展。使用C++ API,可以按以下方式加载扩展:

DuckDB db;
db.LoadExtension<ICUExtension>();

加载此扩展将为您的数据库添加许多语言和地区特定的排序规则。这些可以通过使用PRAGMA collations命令或查询pragma_collations函数来进行查询。

PRAGMA collations;
SELECT * FROM pragma_collations();
[af, am, ar, as, az, be, bg, bn, bo, bs, bs, ca, ceb, chr, cs, cy, da, de, de_AT, dsb, dz, ee, el, en, en_US, en_US, eo, es, et, fa, fa_AF, fi, fil, fo, fr, fr_CA, ga, gl, gu, ha, haw, he, he_IL, hi, hr, hsb, hu, hy, id, id_ID, ig, is, it, ja, ka, kk, kl, km, kn, ko, kok, ku, ky, lb, lkt, ln, lo, lt, lv, mk, ml, mn, mr, ms, mt, my, nb, nb_NO, ne, nl, nn, om, or, pa, pa, pa_IN, pl, ps, pt, ro, ru, se, si, sk, sl, smn, sq, sr, sr, sr_BA, sr_ME, sr_RS, sr, sr_BA, sr_RS, sv, sw, ta, te, th, tk, to, tr, ug, uk, ur, uz, vi, wae, wo, xh, yi, yo, zh, zh, zh_CN, zh_SG, zh, zh_HK, zh_MO, zh_TW, zu]

这些排序规则可以像之前使用其他排序规则一样使用。它们也可以与NOCASE排序规则结合使用。例如,要使用德语排序规则,您可以使用以下代码片段:

CREATE TABLE strings (s VARCHAR COLLATE DE);
INSERT INTO strings VALUES ('Gabel'), ('Göbel'), ('Goethe'), ('Goldmann'), ('Göthe'), ('Götz');
SELECT * FROM strings ORDER BY s;
"Gabel", "Göbel", "Goethe", "Goldmann", "Göthe", "Götz"