22

我是 Android 新手,我正在使用 SQLite 进行查询。我的问题是,当我在字符串中使用重音时,例如

  • 阿阿阿
  • 啊啊啊
  • ÀÀÀ
  • ààà
  • 啊啊啊
  • AAA

如果我做:

SELECT * FROM TB_MOVIE WHERE MOVIE_NAME LIKE '%a%' ORDER BY MOVIE_NAME;

它的回报:

  • AAA
  • aaa(忽略其他)

但如果我这样做:

SELECT * FROM TB_MOVIE WHERE MOVIE_NAME LIKE '%à%' ORDER BY MOVIE_NAME;

它的回报:

  • ààà(忽略标题“ÀÀÀ”)

我想在 SQLite DB 中选择字符串而不关心重音和大小写。请帮忙。

4

4 回答 4

38

通常,SQL 中的字符串比较由列或表达式COLLATE规则控制。在 Android 中,仅预定义了三种排序规则:BINARY(默认)、LOCALIZED 和 UNICODE。它们都不适合您的用例,遗憾的是,用于安装新排序函数的 C API 没有在 Java API 中公开。

要解决此问题:

  1. 例如,在表格中添加另一列MOVIE_NAME_ASCII
  2. 将值存储到此列中,并删除重音符号。您可以通过将字符串规范化为 Unicode 范式 D (NFD) 并删除非 ASCII 代码点来删除重音,因为 NFD 将重音字符大致表示为纯 ASCII + 组合重音标记:

    String asciiName = Normalizer.normalize(unicodeName, Normalizer.Form.NFD)
        .replaceAll("[^\\p{ASCII}]", "");
    
  3. 在这个 ASCII 规范化列上进行文本搜索,但显示来自原始 unicode 列的数据。

于 2013-04-29T16:40:30.353 回答
6

在 Android sqlite 中,LIKE忽略GLOBand COLLATE LOCALIZEDCOLLATE UNICODE它们仅适用于ORDER BY)。但是,有一个解决方案,无需向表中添加额外的列。正如@asat 在此答案中解释的那样,您可以使用GLOB一种模式,该模式将用该字母的所有可用替代品替换每个字母。在 Java 中:

public static String addTildeOptions(String searchText) {
    return searchText.toLowerCase()
                     .replaceAll("[aáàäâã]", "\\[aáàäâã\\]")
                     .replaceAll("[eéèëê]", "\\[eéèëê\\]")
                     .replaceAll("[iíìî]", "\\[iíìî\\]")
                     .replaceAll("[oóòöôõ]", "\\[oóòöôõ\\]")
                     .replaceAll("[uúùüû]", "\\[uúùüû\\]")
                     .replace("*", "[*]")
                     .replace("?", "[?]");
}

然后(当然不是字面意义上的这样):

SELECT * from table WHERE lower(column) GLOB "*addTildeOptions(searchText)*"

这样,例如在西班牙语中,搜索masmás的用户会将搜索转换为m[aáàäâã]s,并返回两个结果。

重要的是要注意GLOBignores COLLATE NOCASE,这就是为什么我在函数和查询中都将所有内容都转换为小写。另请注意lower(),sqlite 中的函数不适用于非 ASCII 字符 - 但这些可能是您已经替换的字符!

该函数还将GLOB通配符*?, 替换为“转义”版本。

于 2019-04-17T09:49:15.533 回答
0

您可以使用 Android NDK 重新编译 SQLite 源代码,包括所需的 ICU(Unicode 国际组件)。在这里用俄语解释:http: //habrahabr.ru/post/122408/

这里解释了使用 ICU 编译 SQLilte 的过程:

如何用ICU编译sqlite?

不幸的是,您最终会得到针对不同 CPU 的不同 APK。

于 2014-11-07T09:15:59.940 回答
-1

您需要查看这些,而不是重音字符,而是完全不同的字符。您不妨寻找 a、b 或 c。话虽如此,我会尝试使用正则表达式。它看起来像:

SELECT * from TB_MOVIE WHERE MOVIE_NAME REGEXP '.*[aAàÀ].*' ORDER BY MOVIE_NAME;
于 2013-04-29T16:18:22.807 回答