在Android Sqlite中使用整理 - 在类似语句中忽略了erentes
题
在Android中创建我的SQLITE数据库时,我设置了数据库语言环境-DB.SetLocale(new Locale(“ CZ_CZ”))。这是一个捷克地区。
选择的语句有效并考虑了该语言环境,例如:
SELECT * from table WHERE name='sctzy' COLLATE LOCALIZED
会找到条目“Ščťžý”。
但是使用会失败:
SELECT * from table WHERE name LIKE '%sctzy%' COLLATE LOCALIZED
没有行返回。
顺便提一句。 Android中没有java.text.Snoralized类。我以为我可以用标准化文本制作第二列,这些文本被剥夺了特殊字符,这些字符将用于搜索 - 但我缺少一个类或方法来正常化字符串。
解决方案
你看过 SQLITE文档类似?它传来了有关非ASCII字符和错误的信息。也许Android已安装了SQLite的较旧版本,这是一个问题。
我认为不幸的是,第二个归一化列可能是您的最佳选择。
其他提示
创建第二个归一化列可用于围绕限制(如其他答案中简要提到)。
这意味着您必须创建第一个(阴影)列的另一个(阴影)列,其中固定情况中相同的数据(例如,所有上部字符)都存储了。可以在此新列上使用搜索值在同一情况下进行案例不敏感的查询(包括类似的查询)。
如果第一列“ a”包含
AAA
AAA
BBB
äää
ééé
第二列A_SHADOW将包含相同行的
AAA
AAA
BBB
ÄÄÄ
ÉÉÉ
和您的原始查询(示例)“从mytable中选择a ='ää'”
将替换为“从mytable中选择a ='ää”'”
添加主内容时,需要更新您的代码以填充转换后的影子内容。如果创建后添加了列,或者您无法更改代码现有值可能需要使用更新查询来转换。例子:
UPDATE mytable SET a_shadow=UPPER(a);
就在今天,我的任务与您的任务完全相同。在我的情况下,制作其他阴影列并不是一个情况,因为我必须搜索多个列。因此,我进入了这样的解决方案,该解决方案已在真实项目中进行了测试。就我而言,我只处理下部案例字母,但您也可以通过上案字母扩展功能。
db.setLocale(Locale("cz", "CZ"))
val query = "SELECT * FROM table WHERE name GLOB ${getExpr(str)} ORDER BY name COLLATE LOCALIZED ASC"
private fun getExpr(input: String) : String{
var expr = ""
for(lettter in input){
expr += when(lettter){
's','š' -> "[sš]"
'a','á' -> "[aá]"
'e','ě','é' -> "[eěé]"
'i','í' -> "[ií]"
'z','ž' -> "[zž]"
'c','č' -> "[cč]"
'y','ý' -> "[yý]"
'r','ř' -> "[rř]"
'u','ů','ú' -> "[uůú]"
'o','ó' -> "[oó]"
'n','ň' -> "[nň]"
'd','ď' -> "[dď]"
't','ť' -> "[tť]"
else -> lettter
}
}
return "'*${expr}*'"
}
可能很耗时,但是您可以在此处使用java.text.normalizer
由于Android的Java子集的一部分不是 normalizer.java与发现的Javadoc 这里:
并复制项目内部所需的代码部分。
希望它有效!
在Android sqlite中, LIKE
和 GLOB
忽略这两个 COLLATE LOCALIZED
和 COLLATE 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)*"
这样,例如,在西班牙语中,用户正在搜索任何一个 马斯 或者 马斯 将使搜索转换为 m [aáàäâf] s, ,返回两个结果。
重要的是要注意 GLOB
忽略 COLLATE NOCASE
, ,这就是为什么我将所有内容转换为功能和查询中的较低情况的原因。还请注意 lower()
sqlite中的功能不适用于非ASCII字符 - 但同样,这些功能可能是您已经替换的那些!
该功能还取代了 GLOB
通配符, *
和 ?
, ,带有“逃脱”版本。