排序规则为执行引擎中的文本排序或比较提供了规则。排序规则对于本地化非常有用,因为不同语言或不同国家的文本排序规则是不同的。这些排序规则通常彼此不兼容。例如,在英语中,字母y
位于x
和z
之间。然而,在立陶宛语中,字母y
位于i
和j
之间。因此,支持不同的排序规则。用户在执行排序和比较操作时必须选择他们想要使用的排序规则。
默认情况下,使用BINARY
排序规则。这意味着字符串仅根据其二进制内容进行排序和比较。这对于标准的ASCII字符(即字母A-Z和数字0-9)是有意义的,但对于特殊的Unicode字符通常没有太大意义。然而,这是迄今为止执行排序和比较的最快方法。因此,除非另有要求,否则建议坚持使用BINARY
排序规则。
使用排序规则
在DuckDB的独立安装中,包含了三种排序规则:NOCASE
、NOACCENT
和 NFC
。NOCASE
排序规则在比较字符时不区分大小写。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"