Question

Lors de la création dans ma base de données SQLite Android I définir les paramètres régionaux de base de données - db.setLocale (nouvelle Locale ( "cz_CZ")). Ceci est un lieu tchèque.

Une instruction SELECT fonctionne et prend les paramètres régionaux en compte, par exemple:

SELECT * from table WHERE name='sctzy' COLLATE LOCALIZED 

Trouvera l'entrée 'ščťžý'.

Mais en utilisant LIKE échouera:

SELECT * from table WHERE name LIKE '%sctzy%' COLLATE LOCALIZED 

Aucune ligne est renvoyée.

BTW. Il n'y a pas de classe java.text.Normalized dans Android. Je pensais que je pouvais faire une deuxième colonne avec un texte normalisé, dépouillé de caractères spéciaux, qui serait utilisé pour la recherche - mais je manque une classe ou comment normaliser ainsi la chaîne

.
Était-ce utile?

La solution

Avez-vous eu un coup d'œil à la SQLite pour LIKE ? Il est venu des informations sur les caractères non ASCII et un bug. Peut-être que Android a une ancienne version de SQLite installée lorsque cela est un problème.

Je pense que la deuxième colonne normalisée pourrait être votre meilleure option, malheureusement.

Autres conseils

Création d'une deuxième colonne normalisée peut être utilisée pour contourner les limites (comme mentionné brièvement dans d'autres réponses).

Cela signifie en pratique que vous devez créer une autre (ombre) colonne de votre première où les mêmes données dans un boîtier fixe (par exemple tous les CHARS supérieurs) sont stockées. requêtes insensible à la casse (y compris comme les requêtes) peuvent être faites sur cette nouvelle colonne avec les valeurs de recherche dans le même cas.

Si la première colonne "a" contient
AAA
aaa
Bbb
aaa
ÉÉÉ
La deuxième colonne a_shadow contiendrait pour des mêmes lignes de
AAA
AAA
BBB
aaa
ÉÉÉ

et votre requête d'origine (par exemple) "sélectionner un de mytable où a = 'aaa'"
serait remplacé par « choisir un de mytable où A = « aaa » »

Votre code doit être mis à jour pour remplir le contenu de l'ombre convertie lors de l'ajout du contenu principal. Si la colonne est ajoutée après la création ou vous ne pouvez pas modifier le code des valeurs existantes peuvent avoir besoin d'être convertis à l'aide d'une requête de mise à jour. Exemple:

UPDATE mytable SET a_shadow=UPPER(a);

Aujourd'hui encore j'ai eu exactement la même tâche que vous aviez. Et dans ma situation faisant des colonnes d'ombre supplémentaires ne sont pas un cas parce que je vais avoir à rechercher plus d'une colonne. Donc, je suis venu à la solution comme celui-ci, qui est testé en vrai projet. Dans mon cas, je suis la manipulation des lettres seulement des minuscules mais vous pouvez étendre la fonction avec des lettres majuscules ainsi.

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

peut prendre beaucoup de temps, mais vous pouvez utiliser le java.text.Normalizer comme ici

Conversion des symboles, lettres Accent Anglais Alphabet

ne fait pas partie du sous-ensemble de Java Android, vous pouvez essayer de chercher le code de Java, tels que Normalizer.java Avec le Javadoc trouvé :

Et copier la partie du code nécessaire à l'intérieur de votre projet.

Hope ça marche!

Dans Android sqlite, LIKE et GLOB ignorent à la fois COLLATE LOCALIZED et COLLATE UNICODE (ils ne le travail pour ORDER BY). Cependant, comme @asat explique sa réponse , vous pouvez utiliser GLOB avec un motif qui remplacera chaque lettre avec tous les disponibles alternatives de cette lettre. En 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("?", "[?]");
}

Et puis (pas littéralement comme ça, bien sûr):

SELECT * from table WHERE lower(column) GLOB "*addTildeOptions(searchText)*"

De cette façon, par exemple en espagnol, une recherche d'utilisateur pour les deux mas ou más obtenir la recherche convertie en m [Aaaaaa] s , retour les résultats.

Il est important de noter que GLOB ne tient pas compte COLLATE NOCASE, qui est la raison pour laquelle je me suis converti tout en minuscules aussi bien dans la fonction et dans la requête. Notez également que la fonction lower() dans SQLite ne fonctionne pas sur des caractères non-ASCII - mais encore une fois ce sont probablement ceux que vous êtes déjà en remplaçant

La fonction remplace aussi les deux jokers GLOB, * et ?, avec "échappé" versions.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top