5

我想比较 SQLite DB 中的两个字符串,而不关心重音和大小写。我的意思是“É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 文档确认这是应用排序规则的正确方法。我认为这个 ICU 扩展的文档有点轻(很少有例子,没有关于排序规则的区分大小写)。

我不明白为什么COLLATE操作员在我上面的例子中没有效果。请帮忙。

4

1 回答 1

6

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

我终于明白了,我需要的是 将排序规则 的强度设置为一级级别 ,而不是默认的三级。

我发现无法通过语言环境进行设置(例如,几个变体SELECT icu_load_collation('fr_FR,strength=0', 'french')无用)。所以唯一的解决方案是修补 SQLite 的代码。由于ICU APIucol_setStrength()中的功能,这很容易。

最小的变化是一行补丁:在函数ucol_setStrength(pUCollator, 0);后面添加一行。对于向后兼容的更改,我添加了一个可选的第三个参数来设置强度:默认为 0,主要为 1,等等。最多为 4-quaternary。见差异pUCollator = ucol_open(zLocale, &status);icuLoadCollation()icu_load_collation()

最后我得到了我想要的:

SELECT icu_load_collation('fr_FR', 'french_ci', 1); -- collation with strength=primary
SELECT 'Événement' COLLATE french_ci = 'evenèment';
-- 1
于 2013-02-25T10:12:50.007 回答