在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中, LIKEGLOB 忽略这两个 COLLATE LOCALIZEDCOLLATE 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 通配符, *?, ,带有“逃脱”版本。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top