Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Android SQLite中使用COLLATE-Locales在LIKE语句中被忽略_Android_Database_Sqlite_Locale_Collate - Fatal编程技术网

在Android SQLite中使用COLLATE-Locales在LIKE语句中被忽略

在Android SQLite中使用COLLATE-Locales在LIKE语句中被忽略,android,database,sqlite,locale,collate,Android,Database,Sqlite,Locale,Collate,在Android中创建SQLite数据库时,我设置了数据库区域设置-db.setLocale(new locale(“cz_-cz”))。这是捷克的地方 SELECT语句起作用并考虑到区域设置,例如: SELECT * from table WHERE name='sctzy' COLLATE LOCALIZED 将找到条目“ťťý” 但使用LIKE将失败: SELECT * from table WHERE name LIKE '%sctzy%' COLLATE LOCALIZED 不

在Android中创建SQLite数据库时,我设置了数据库区域设置-db.setLocale(new locale(“cz_-cz”))。这是捷克的地方

SELECT语句起作用并考虑到区域设置,例如:

SELECT * from table WHERE name='sctzy' COLLATE LOCALIZED 
将找到条目“ťťý”

但使用LIKE将失败:

SELECT * from table WHERE name LIKE '%sctzy%' COLLATE LOCALIZED 
不返回任何行


顺便说一句,Android中没有java.text.Normalized类。我想我可以用规范化文本创建第二列,去掉特殊字符,用于搜索-但我缺少一个类或如何规范化字符串的方法。

你看了吗?它提供了有关非ASCII字符和错误的信息。可能Android安装了一个较旧版本的SQLite,这是一个问题


不幸的是,我认为第二个标准化列可能是您最好的选择。

可能很耗时,但您可以像这里一样使用java.text.Normalizer

由于Android不是java子集的一部分,您可以尝试在java代码中查找它,例如 找到Javadoc后:

并复制项目中所需的部分代码


希望它能起作用

创建第二个标准化列可用于绕过限制(如其他答案中简要提到的)

这意味着在实践中,您必须创建第一列的另一个(阴影)列,其中存储固定大小写中的相同数据(例如,所有大写字符)。可以对这个新列进行不区分大小写的查询(包括like查询),搜索值大小写相同

如果第一列“a”包含

AAA
aaa
Bbb
äää


第二列a_shadow将包含相同行的值

AAA
AAA
BBB
ÄÄ
ÉÉ

原始查询(示例)“从mytable中选择一个,其中a='ääää'”
将替换为“从mytable中选择a,其中a=‘ÄÄÄ’”

添加主内容时,需要更新代码以填充转换后的卷影内容。 如果列是在创建后添加的,或者无法更改代码,则可能需要使用更新查询转换现有值。例如:


updatemytable 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}*'"
}

在Android sqlite中,
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("?", "[?]");
}
然后(当然不是字面上的意思):

这样,例如在西班牙语中,搜索mas或más的用户将把搜索转换为m[aááääs],并返回两个结果

需要注意的是,
GLOB
忽略了
COLLATE NOCASE
,这就是为什么我将函数和查询中的所有内容都转换为小写。还请注意,sqlite中的
lower()
函数对非ASCII字符不起作用,但这些字符可能已经被替换了


该函数还用“转义”版本替换了
GLOB
通配符、
*

我在这里找到了一个部分答案:但这只是删除重音符号的方法。我将不得不在我的数据库中使用规范化文本创建一个重复列。。。难道没有更好的方法吗?如何创建规范化列?我必须修复正则表达式才能使其工作,因为它是反向的。其中是
.replaceAll(“[aáää]”,“\\[aáää]”
我不得不使用
.replaceAll(“\\\.[aáää]\\.”,“[aáää]”
SELECT * from table WHERE lower(column) GLOB "*addTildeOptions(searchText)*"