⌘+k ctrl+k
1.3 (稳定版)
搜索快捷键 cmd + k | ctrl + k
排序规则

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

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

BINARY 排序规则也可用作 CPOSIX 的别名。

警告 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;
name other_name
hännes HÄNNES

ICU 排序规则

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

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

PRAGMA collations;
SELECT list(collname) FROM pragma_collations();
[af, am, ar, ar_sa, as, az, be, bg, bn, bo, br, bs, ca, ceb, chr, cs, cy, da, de, de_at, dsb, dz, ee, el, en, en_us, eo, es, et, fa, fa_af, ff, fi, fil, fo, fr, fr_ca, fy, ga, gl, gu, ha, haw, he, he_il, hi, hr, hsb, hu, hy, icu_noaccent, 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, nfc, nl, nn, noaccent, nocase, om, or, pa, pa_in, pl, ps, pt, ro, ru, sa, se, si, sk, sl, smn, sq, sr, sr_ba, sr_me, sr_rs, sv, sw, ta, te, th, tk, to, tr, ug, uk, ur, uz, vi, wae, wo, xh, yi, yo, yue, yue_cn, zh, zh_cn, zh_hk, zh_mo, zh_sg, 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"