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

qyyhg6bp  于 2022-12-23  发布在  SQLite
关注(0)|答案(4)|浏览(139)

我是新的Android和我的工作在SQLite查询。我的问题是,当我使用重音字符串,例如。

  • 阿阿
  • 阿阿
  • 阿拉
  • 阿阿
  • 美国汽车协会
  • 美国汽车协会

如果我这样做:

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

它的回报:

  • 美国汽车协会
  • aaa(它忽略其他项)

但如果我这么做了:

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

它的回报:

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

我想在一个SQLite数据库中选择字符串,而不考虑重音和大小写。请帮助。

6yoyoihd

6yoyoihd1#

通常,SQL中的字符串比较由列或表达式COLLATE规则控制。在Android中,只有三个排序规则序列是pre-defined:BINARY(默认)、LOCALIZED和UNICODE。它们都不适合您的用例,而且不幸的是,用于安装新排序函数的C API没有在Java API中公开。
要解决此问题:
1.向表中添加另一列,例如MOVIE_NAME_ASCII
1.将值存储到此列中,并删除重音符号。可以通过将字符串规范化为Unicode范式D(NFD)并删除非ASCII码位来删除重音符号,因为NFD将重音字符大致表示为纯ASCII +组合重音符号:

String asciiName = Normalizer.normalize(unicodeName, Normalizer.Form.NFD)
    .replaceAll("[^\\p{ASCII}]", "");

1.在这个ASCII规范化列上执行文本搜索,但显示原始unicode列中的数据。

scyqe7ek

scyqe7ek2#

在Android sqlite中,LIKEGLOB忽略COLLATE LOCALIZEDCOLLATE UNICODE(它们只适用于ORDER BY)。然而,有一个解决方案,无需向表中添加额外的列。正如@asat在this answer中所解释的,您可以使用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,返回两个结果。
值得注意的是GLOB忽略了COLLATE NOCASE,这就是为什么我把函数和查询中的所有内容都转换成小写的原因。还需要注意的是,sqlite中的lower()函数不适用于非ASCII字符--但同样,这些字符可能是您已经替换的字符!
该函数还将GLOB通配符*?替换为“转义”版本。

gcmastyq

gcmastyq3#

您可以使用Android NDK重新编译SQLite源代码,包括所需的ICU(Unicode国际组件)。http://habrahabr.ru/post/122408/
使用ICU源代码编译SQLilte的过程如下所述:
How to compile sqlite with ICU?
不幸的是,您最终会为不同的CPU使用不同的APK。

irtuqstp

irtuqstp4#

你需要把这些字符看作完全不同的字符,而不是重音字符,你可能需要寻找a、b或c。也就是说,我会尝试使用正则表达式。它看起来像这样:

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

相关问题