我有一个列,其中一些元素包含重音字母。例如:Grambú
我的要求是,当我搜索“Grambu”时,我也应该在结果中获得“Grambú”。
对于此要求,我尝试对该特定列使用“COLLATE NOCASE”参数。但那没有用。
当我在网上搜索解决方案时,我发现许多人建议对重音字符进行规范化,并根据它创建另一个列作为唯一选项。
这个问题还有其他更简单的解决方案吗?
COLLATE NOCASE
工作only for the 26 upper case characters of ASCII。
使用setLocale()
将数据库的语言环境设置为具有重音字符支持的语言环境,并使用COLLATE LOCALIZED
。
您也可以尝试使用COLLATE UNICODE
。但要注意这个错误:SQLite UNICODE sort broken in ICS - no longer case-insensitive。
检查the documentation在Android中提到这两个合作者。
还可以看看这个online collation demo tool。
http://www.sqlite.org/lang_expr.html
(一个错误:默认情况下,SQLite只能理解ASCII字符的大写/小写。对于超出ASCII范围的unicode字符,LIKE运算符默认区分大小写。例如,表达式'a'LIKE'A'为TRUE但是'æ'LIKE'Æ'是假的。)
在Android sqlite中,LIKE
和GLOB
忽略了COLLATE LOCALIZED
和COLLATE UNICODE
。但是,有一个解决方案,无需在表中添加额外的列。正如@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)*"
这样,搜索Grambu或Grambú的用户将搜索转换为Gramb [uúùüû],返回两个结果。
重要的是要注意GLOB
忽略COLLATE NOCASE
,这就是我在函数和查询中将所有内容都转换为小写的原因。另请注意,sqlite中的lower()
函数不适用于非ASCII字符 - 但这些可能是您已经替换的那些!
该函数还用“转义”版本替换了GLOB
通配符,*
和?
。