web-dev-qa-db-fra.com

Comment définir Sqlite3 pour qu'il ne respecte pas la casse lors de la comparaison de chaînes?

Je veux sélectionner des enregistrements de la base de données sqlite3 par correspondance. Mais si j'utilise '=' dans la clause where, je trouve que sqlite3 est sensible à la casse. Quelqu'un peut-il me dire comment utiliser des chaînes comparant la casse?

259
quantity

Vous pouvez utiliser COLLATE NOCASE dans votre requête SELECT:

SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE

De plus, dans SQLite, vous pouvez indiquer qu'une colonne doit être sensible à la casse lorsque vous créez la table en spécifiant collate nocase dans la définition de colonne (les autres options sont binary (valeur par défaut) et rtrim; voir ici ). Vous pouvez également spécifier collate nocase lorsque vous créez un index. Par exemple:

 create table Test 
 (
 Text_Value text collate nocase 
); 

 insérer dans les valeurs de test ('A'); 
 insérer dans les valeurs de test ('b') ; 
 insérer dans les valeurs de test ('C'); 

 créer un index Test_Text_Value_Index 
 sur Test (Text_Value collate nocase); 

Les expressions impliquant Test.Text_Value devraient maintenant être insensibles à la casse. Par exemple:

 sqlite> sélectionnez Text_Value dans Test où Text_Value = 'B'; 
 Text_Value 
 ---------------- 
 b 

 sqlite > sélectionnez Text_Value dans Test order by Text_Value; 
 Text_Value 
 ---------------- 
 A 
 b 
 C 

 sqlite> sélectionnez Text_Value dans Test order by Text_Value desc; 
 Text_Value 
 ---------------- 
 C 
 b 
 A 

L'optimiseur peut également potentiellement utiliser l'index pour une recherche et une correspondance respectant la casse sur la colonne. Vous pouvez le vérifier en utilisant la commande SQL explain, par exemple:

 sqlite> explicitement sélectionner Text_Value from Test où Text_Value = 'b'; 
 addr opcode p1 p2 p3 
---------------- ------ -------- ---------- ---------- ---------------------- -----------
 0 Goto 0 16 
 1 Entier 0 0 
 2 OpenRead 1 3 keyinfo (1, NOCASE) 
 3 SetNumColumns 1 2 
 4 String8 0 0 b 
 5 IsNull -1 14 
 6 MakeRecord 1 0 a 
 7 MemStore 0 0 
 8 MoveGe 1 14 
 9 MemLoad 0 0 
 10 IdxGE 1 14 + 
 11 Colonne 1 0 
 12 Rappel 1 0 
 13 Suivant 1 9 
 14 Fermer 1 0 
 15 Arrêt 0 0 
 16 Transaction 0 0 
 17 VerifyCookie 0 4 
 18 Goto 0 1 
 19 Noop 0 0 
425
cheduardo
SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE
144
Craz

Vous pouvez le faire comme ça:

SELECT * FROM ... WHERE name LIKE 'someone'

(Ce n'est pas la solution, mais dans certains cas c'est très pratique)

"L'opérateurLIKEeffectue une comparaison de correspondance de motif L'opérande à À droite contient le motif, l'opérande à gauche Contient la chaîne À faire correspondre au motif. Un symbole Pourcent ("%") dans le motif Correspond à toute séquence de zéro ou plus caractères De la chaîne. Un trait de soulignement .__ ("_") dans le motif caractère unique dans la chaîne Tout autre caractère correspond à lui-même ou à ses majuscules/minuscules équivalent (c'est-à-dire non sensible à la casse correspondance ) . (Un bogue: SQLite uniquement Comprend les majuscules/minuscules pour les caractères ASCII . L'opérateur LIKE est sensible à la casse Pour les caractères unicode dont Dépasse la plage ASCII Par exemple, , L'expression 'a' LIKE 'A' Est TRUE mais 'æ' LIKE 'Æ' est FALSE.). "

39
Nick Dandoulakis

Ce n'est pas spécifique à sqlite mais vous pouvez simplement faire

SELECT * FROM ... WHERE UPPER(name) = UPPER('someone')
35
oscarkuo

Une autre option consiste à créer votre propre classement personnalisé. Vous pouvez ensuite définir ce classement sur la colonne ou l'ajouter à vos clauses de sélection. Il sera utilisé pour les commandes et les comparaisons.

Ceci peut être utilisé pour faire 'VOILA' LIKE 'voilà.

http://www.sqlite.org/capi3ref.html#sqlite3_create_collation

La fonction de classement doit renvoyer un entier négatif, nul ou positif si la première chaîne est inférieure, égale ou supérieure à la seconde, respectivement.

2
Nick Ericson

Une autre option qui peut avoir un sens dans votre cas est d’avoir une colonne distincte avec les valeurs pré-inférieures de votre colonne existante. Cela peut être renseigné à l'aide de la fonction SQLite LOWER() et vous pouvez ensuite effectuer une correspondance sur cette colonne. 

Évidemment, cela ajoute de la redondance et un risque d'incohérence, mais si vos données sont statiques, cela pourrait être une option appropriée.

1
Magnus W

Simplement, vous pouvez utiliser COLLATE NOCASE dans votre requête SELECT:

SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE
0
Pullat Junaid

vous pouvez utiliser la même requête pour comparer la chaîne respective aux valeurs de la table.

sélectionnez le nom de la colonne à partir du nom_table où le nom de la colonne ressemble à 'valeur de comparaison respective';

0
Mahendranatarajan

Cela fonctionne pour moi parfaitement. SELECT NAME FROM TABLE_NAME WHERE NAME = 'test Name' COLLATE NOCASE

0
Shohel Rana

Si la colonne est de type char, vous devez ajouter la valeur que vous interrogez avec des espaces, veuillez vous reporter à cette question ici . Ceci en plus d'utiliser COLLATE NOCASE ou l'une des autres solutions (upper (), etc.).

0
Has AlTaiar