SQLite字符串比较上的本地化COLLATE

时间:2013-02-24 10:50:31

标签: unicode sqlite

我想比较SQLite数据库中的两个字符串而不关心重音和大小写。我的意思是“Événement”应该等于“evenèment”。

在Debian Wheezy上,SQLite包不提供ICU。所以我编译了包含ICU模块的官方SQLite包(版本3.7.15.2 2013-01-09 11:53:05)。现在,我确实有更好的Unicode支持(原始lower()仅应用于ASCII字符,现在它适用于其他字母)。但我无法将比对应用于整理。

SELECT icu_load_collation('fr_FR', 'FRENCH');
SELECT 'événement' COLLATE FRENCH = 'evenement';
-- 0 (should be 1)
SELECT 'Événement' COLLATE FRENCH = 'événement';
-- 0 (should be 1 if collation was case-insensitive)
SELECT lower('Événement') = 'événement';
-- 1 (at least lower() works as expected with Unicode strings)

SQLite documentation确认这是应用排序规则的正确方法。我认为documentation of this ICU extension有点轻(几个例子,没有关于整理的区分大小写)。

我不明白为什么COLLATE运算符在我上面的示例中没有效果。请帮忙。

1 个答案:

答案 0 :(得分:6)

我花了好几个小时来了解情况......在SQLite中定义ICU排序规则的方式(几乎)没有比较的发生率。根据ICU的说法,例外情况是带有灌注标记的希伯来文本。这是ICU库的排序规则的默认行为。使用SQLite时,LIKE在加载ICU时变得不区分大小写,但是不能通过这种方式实现加重字母的规范化。

我终于明白我需要的是设置 strength 整理的 primary level 而不是默认的高等级。

我发现无法通过语言环境进行设置 (例如SELECT icu_load_collation('fr_FR,strength=0', 'french')的几个变体是无用的)。 所以唯一的解决方案就是修补SQLite的代码。 感谢ucol_setStrength()函数很容易 在ICU API

最小变化是单行补丁:在ucol_setStrength(pUCollator, 0);函数pUCollator = ucol_open(zLocale, &status);之后添加行icuLoadCollation()。 对于向后兼容的更改,我向icu_load_collation()添加了可选的第三个参数来设置强度: 0表示默认,1表示主要,等等,最多4个四元。 请参阅diff

最后我有我想要的东西:

SELECT icu_load_collation('fr_FR', 'french_ci', 1); -- collation with strength=primary
SELECT 'Événement' COLLATE french_ci = 'evenèment';
-- 1