如何在SQLite查询(Android)中忽略重音

如何在SQLite查询(Android)中忽略重音,android,sqlite,diacritics,Android,Sqlite,Diacritics,我是Android新手,正在SQLite中进行查询。 我的问题是,当我在字符串中使用重音时,例如 ÁÁÁ 亚亚加拉 ÀÀÀ 同上 aaa 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 MO

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

  • ÁÁÁ
  • 亚亚加拉
  • ÀÀÀ
  • 同上
  • aaa
  • 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数据库中选择字符串,而不考虑重音和大小写。请帮助。

您需要将这些字符视为完全不同的字符,而不是重音字符。你最好找a、b或c。也就是说,我会尝试使用正则表达式。它看起来像:

SELECT * from TB_MOVIE WHERE MOVIE_NAME REGEXP '.*[aAàÀ].*' ORDER BY MOVIE_NAME;

通常,SQL中的字符串比较由列或表达式
COLLATE
规则控制。在Android中,只有三种排序顺序:二进制(默认)、本地化和UNICODE。它们都不适合您的用例,而且用于安装新排序规则函数的C API不幸没有在Java API中公开

要解决此问题,请执行以下操作:

  • 向表中添加另一列,例如
    MOVIE\u NAME\u ASCII
  • 将删除重音标记的值存储到此列中。您可以通过将字符串规范化为Unicode标准格式D(NFD)并删除非ASCII码点来删除重音符号,因为NFD将重音字符大致表示为普通ASCII+组合重音符号:

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


  • 您可以使用Android NDK重新编译SQLite源代码,包括所需的ICU(Unicode的国际组件)。 此处用俄语解释:

    下面解释了使用ICU的source编译SQLilte的过程:


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

    在Android sqlite中,
    GLOB
    忽略
    校对本地化的
    校对UNICODE
    (它们只适用于
    按顺序
    )。但是,有一种解决方案不必向表中添加额外的列。正如@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("?", "[?]");
    }
    
    然后(当然不是字面上的意思):

    这样,例如在西班牙语中,搜索mas或más的用户将把搜索转换为m[aááääs],并返回两个结果

    需要注意的是,
    GLOB
    忽略了
    COLLATE NOCASE
    ,这就是为什么我将函数和查询中的所有内容都转换为小写。还请注意,sqlite中的
    lower()
    函数对非ASCII字符不起作用,但这些字符可能已经被替换了


    该函数还用“转义”版本替换了
    GLOB
    通配符、
    *

    可能重复的不重复到上面-它是关于正确排序重音字符(大写/小写匹配),而不是忽略它们。对我来说也适用,但我想知道是否没有其他方法可以做到这一点,我必须修复你的正则表达式才能让它工作,因为它是反向的。其中是
    .replaceAll(“[aáää]”,“\\[aáää]”
    我不得不使用
    .replaceAll(“\\\.[aáää]\\.”,“[aáää]”
    SELECT * from table WHERE lower(column) GLOB "*addTildeOptions(searchText)*"