我是Android的新手,我正在使用SQLite进行查询。我的问题是当我在字符串中使用重音例如
如果我做:
SELECT * FROM TB_MOVIE WHERE MOVIE_NAME LIKE '%a%' ORDER BY MOVIE_NAME;
回归:
但如果我这样做:
SELECT * FROM TB_MOVIE WHERE MOVIE_NAME LIKE '%à%' ORDER BY MOVIE_NAME;
回归:
我想在SQLite数据库中选择字符串而不关心重音和大小写。请帮忙。
通常,SQL中的字符串比较由列或表达式COLLATE
规则控制。在Android中,只有三个校对序列是pre-defined:BINARY(默认),LOCALIZED和UNICODE。它们都不适合您的用例,遗憾的是,Java API中没有公开用于安装新归类函数的C API。
要解决这个问题:
MOVIE_NAME_ASCII
String asciiName = Normalizer.normalize(unicodeName, Normalizer.Form.NFD)
.replaceAll("[^\\p{ASCII}]", "");
在Android sqlite中,LIKE
和GLOB
忽略了COLLATE LOCALIZED
和COLLATE 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)*"
这样,例如在西班牙语中,搜索mas或más的用户将搜索转换为m [aáàäâ],返回两个结果。
重要的是要注意GLOB
忽略COLLATE NOCASE
,这就是我在函数和查询中将所有内容都转换为小写的原因。另请注意,sqlite中的lower()
函数不适用于非ASCII字符 - 但这些可能是您已经替换的那些!
该函数还用“转义”版本替换了GLOB
通配符,*
和?
。
您可以使用Android NDK重新编译SQLite源,包括所需的ICU(Unicode的国际组件)。在这里用俄语解释:http://habrahabr.ru/post/122408/
使用ICU编译带有源代码的SQLilte的过程如下所述:
How to compile sqlite with ICU?
不幸的是,您最终会针对不同的CPU使用不同的APK。
您需要查看这些,而不是重音字符,而是完全不同的字符。您也可以寻找a,b或c。话虽这么说,我会尝试使用正则表达式。它看起来像:
SELECT * from TB_MOVIE WHERE MOVIE_NAME REGEXP '.*[aAàÀ].*' ORDER BY MOVIE_NAME;