Comment faire une recherche sensible à la casse dans la clause WHERE?

21

Je veux une recherche sensible à la casse dans la requête SQL. Mais par défaut, MySQL ne prend pas en compte le cas des chaînes.

Une idée sur la façon de faire une recherche sensible à la casse dans une requête SQL?

Somnath Muluk
la source

Réponses:

22

par défaut, MySQL ne considère pas le cas des chaînes

Ce n'est pas tout à fait vrai. Chaque fois que vous create databasedans MySQL, la base de données / schéma a un jeu de caractères et un classement. Chaque jeu de caractères a un classement par défaut; voir ici pour plus d'informations.

Le classement par défaut pour le jeu de caractères latin1, qui est latin1_swedish_ci, se trouve être insensible à la casse.

Vous pouvez choisir un classement sensible à la casse, par exemple latin1_general_cs( grammaire MySQL ):

CREATE SCHEMA IF NOT EXISTS `myschema` 
DEFAULT CHARACTER SET latin1 
COLLATE latin1_general_cs ;

Cela a un effet sur des choses comme le regroupement et l'égalité. Par exemple,

create table casetable (
  id int primary key, 
  thing varchar(50)
);

select * from casetable;
+----+-------+
| id | thing |
+----+-------+
|  3 | abc   |
|  4 | ABC   |
|  5 | aBc   |
|  6 | abC   |
+----+-------+

Dans une base de données sensible à la casse, nous obtenons:

select thing, count(*) from casetable group by thing;
+-------+----------+
| thing | count(*) |
+-------+----------+
| ABC   |        1 |
| aBc   |        1 |
| abC   |        1 |
| abc   |        1 |
+-------+----------+

select * from casetable where thing = "abc";
+----+-------+
| id | thing |
+----+-------+
|  3 | abc   |
+----+-------+

Dans une base de données insensible à la casse, nous obtenons:

select thing, count(*) from casetable group by thing;
+-------+----------+
| thing | count(*) |
+-------+----------+
| abc   |        4 |
+-------+----------+

select * from casetable where thing = "abc";
+----+-------+
| id | thing |
+----+-------+
|  3 | abc   |
|  4 | ABC   |
|  5 | aBc   |
|  6 | abC   |
+----+-------+

Notez que vous pouvez également modifier le classement à partir d'une requête . Par exemple, dans la base de données sensible à la casse , je peux faire

select * from casetable where thing collate latin1_swedish_ci = "abc";
+----+-------+
| id | thing |
+----+-------+
|  3 | abc   |
|  4 | ABC   |
|  5 | aBc   |
|  6 | abC   |
+----+-------+
Matt Fenwick
la source
13

Vous devez toujours indiquer avec votre question quelle version de MySQL vous utilisez, car MySQL est en développement constant.

Bon, revenons à votre question:

Les fonctions de chaîne dans MySQL sont toujours sensibles à la casse, vous pouvez donc utiliser toutes les fonctions LOCATE, POSITIONou INSTR.

Par exemple:

SELECT phone FROM user WHERE POSITION('term' IN user_name)>0;

La correspondance de modèle avec l'expression régulière ( RLIKEou REGEXP) est toujours sensible à la casse pour toutes les versions de MySQL, à l'exception de la dernière 3.23.4.

Par exemple:

SELECT phone FROM user WHERE user_name REGEXP 'term';

Pour la comparaison normale (=) et la correspondance de modèle SQL ( LIKE), le comportement dépend des champs impliqués:

une. CHAR, VARCHARet toutes les variantes des champs TEXT ne comparent pas la casse.

b. CHAR BINARY, VARCHAR BINARY Et toutes les variantes de champs BLOB ne se comparent sensible à la casse.

Si vous comparez un champ de (a) avec un champ de (b), la comparaison sera sensible à la casse (la sensibilité à la casse l'emporte). Voir le chapitre "7.2.7 Types de chaînes" du Manuel de référence MySQL et recherchez les instructions sur le tri et les comparaisons.

À partir de la version V3.23.0, il est également possible de forcer une comparaison en respectant la casse avec l'opérateur de transtypage BINARY, indépendamment des types de champs impliqués. Voir le chapitre "7.3.7 Opérateurs Cast" du Manuel de référence MySQL.

Vous pouvez donc également changer le type de nom_utilisateur, ou avec V3.23.x, essayez quelque chose comme:

SELECT phone FROM user WHERE BINARY username LIKE '%term%';
Turgut
la source
1

Dans ma situation, j'utilise Access 2010, mais j'ai eu le même problème mais la solution est différente: utilisez la StrComp()fonction et testez son retour à zéro.

StrComp( thing, 'abc', 0) = 0

Parce que StrComp()retourne -1si le premier argument est "plus petit", 1s'il est "plus grand" et 0s'il est "égal", quand StrComp()=0, vous avez une correspondance sensible à la casse.

Voir ici , ici ou ici .

Martin F
la source
0

Cela fonctionnera dans MySQL quel que soit le jeu de caractères. SÉLECTIONNEZ 'test' REGEXP BINARY 'TEST' COMME RÉSULTAT; Mettre 'BINARY' force une comparaison binaire.

user2288580
la source
-2

Essayez ceci pour une recherche insensible, cela fonctionne très bien avec de grandes performances:

"SELECT phone FROM user WHERE lower(user_name) like ".srtlower($username);
ganji
la source