Sélection insensible à la casse MySQL


242

Quelqu'un peut-il me dire si une SELECTrequête MySQL est sensible à la casse ou à la casse par défaut? Et sinon, quelle requête devrais-je envoyer pour que je puisse faire quelque chose comme:

SELECT * FROM `table` WHERE `Value` = "iaresavage"

Alors qu'en réalité, la valeur réelle de Valueest IAreSavage.


44
En fin de compte, cela dépend du classement déposé - si c'est '_ci' (insensible à la casse) ou '_cs' (sensible à la casse)
Jovan Perovic

15
C'est une question mal formulée;). La moitié des réponses vous montre comment faire une comparaison insensible à la casse, la moitié vise la casse. Et seulement 1 vous indique que la valeur par défaut est en fait insensible à la casse. :) Il convient de noter que l'insensibilité à la casse fonctionne même lorsque vous faites une comparaison comme'value' in ('val1', 'val2', 'val3')
SaltyNuts

5
@SaltyNuts man, lisant cette question 7 ans plus tard et réalisant à quel point j'étais un noob embarrassant! J'aurais pu lire la documentation et la réponse est comme la première phrase sur les instructions SELECT ...
NoodleOfDeath

Pour ajouter à ce que @JovanPerovic a dit, utf8_bin le rend également sensible à la casse. Je ne sais pas si cela existait à l'époque
Chiwda

Réponses:


494

Ils ne sont pas sensibles à la casse , sauf si vous effectuez une comparaison binaire .


3
Je suis principalement d'accord avec le commentaire de Tim, je ne pense pas que faire un "inférieur ()" sur vos valeurs partout soit la meilleure façon de le gérer, semble être une solution de contournement. Mais je l'admets parfois, cela a du sens et c'est plus facile. (Colin a mentionné que l'assemblage était meilleur) Nous avons déplacé les données historiques dans la table mysql qui a rompu la logique héritée en raison de certaines valeurs de colonne ayant une casse insensible. Nous devions connaître la différence entre "GE1234" et "ge1234", ils devaient être uniques et rester connectés de cette façon. À la place, nous définissons notre colonne dans l'instruction create table: varchar (20) CHARACTER SET utf8 COLLATE utf8_bin
gregthegeek

19
Je ne sais pas pourquoi tant de gens ont voté pour cela. Il indique clairement ici dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html que "... cela signifie que pour les caractères alphabétiques, les comparaisons seront sensibles à la casse." Donc, si je cherche «DickSavagewood», il ne ramassera PAS «dicksavagewood». Faire de même avec LOWER () LE ramassera. Donc, ma réponse à la question: dans votre cas particulier, le SELECT est en effet sensible à la casse.
Luftwaffle

10
@ user1961753: Relisez: "Pour les chaînes binaires (varbinary, blob) ... sera sensible à la casse".
Marc B

1
@MarcB ce lien est maintenant rompu. Pourriez-vous le réparer? :)
Phiter

5
Comme l'a dit Jovan, cela dépend du classement, donc cette réponse est à peu près fausse.
phil294

117

Vous pouvez minuscule la valeur et le paramètre passé:

SELECT * FROM `table` WHERE LOWER(`Value`) = LOWER("IAreSavage")

Une autre (meilleure) façon serait d'utiliser l' COLLATEopérateur comme indiqué dans la documentation


21
À quoi SELECTressemblerait cette déclaration COLLATEalors?
Oui Barry

11
Il indique, sur la page de documentation mentionnée ci-dessus, que "les comparaisons de chaînes non binaires ne respectent pas la casse par défaut".
Per Quested Aronsson

9
Un peu terrifiant combien de personnes ont voté pour cette réponse. Comme @Marc l'explique ci-dessus, les comparaisons ne sont pas sensibles à la casse. Vous devez comprendre les classements et les index et les configurer correctement.Utiliser des transformations de chaînes comme LOWER()ou une COLLATEclause arbitraire peut complètement contourner un index, et au fil du temps, à mesure que votre table grandit, cela peut avoir des implications drastiques sur les performances. Ce sont probablement des noms d'utilisateur que vous recherchez? Utilisez un classement insensible à la casse et ajoutez un index unique à la colonne. Utilisez EXPLAINpour confirmer que l'index est utilisé.
mindplay.dk

1
J'étais sur le point de dire la même chose que mindplay.dk ... upper () et lower () contournent l'index et affectent directement les performances sur les grandes tables de base de données.
GTodorov

Je partage les opinions de mindplay.dk et de GTodorov. Soyez prudent en utilisant une méthode sur une colonne cible dans la clause where. L'index de la colonne peut être inutile. Utilisez EXPLAIN!
traeper

51

UTILISER BINARY

Ceci est une simple sélection

SELECT * FROM myTable WHERE 'something' = 'Something'

= 1

Ceci est une sélection avec binaire

SELECT * FROM myTable WHERE BINARY 'something' = 'Something'

ou

SELECT * FROM myTable WHERE 'something' = BINARY 'Something'

= 0


3
Quand est-il judicieux d'utiliser BINARY sur un seul côté du = (SELECT * FROM myTable WHERE BINARY 'something' = 'Something')?
Jimmy

@Jimmy Que voulez-vous dire exactement? Le code fonctionne. Lorsqu'un côté de la comparaison est converti en binaire, la comparaison est binaire.
Jori

@Jori Oh, je suppose que j'ai mal lu - je pensais que l'un des deux exemples avait BINARY des deux côtés de l'égalité.
Jimmy

Je viens de voter parce que c'est vraiment la bonne réponse. Selon la documentation sur le site Web MySQL, ils disent qu'il vaut mieux utiliser la commande BINARY que d'essayer de transtyper vos mots / demande dans une langue spécifique parce que la commande BINARY dit de tout laisser tel quel et de l'utiliser exactement comme il est présenté. Donc, quand je suis venu chercher une réponse - les deux réponses ici m'ont conduit au site Web MySQL et à regarder leur documentation. Il est préférable d'utiliser BINARY. La traduction peut entraîner d'autres problèmes.
Mark Manning du

43

Les comparaisons ne respectent pas la casse lorsque la colonne utilise un classement qui se termine par _ci(comme le classement par défaut latin1_general_ci ) et sont sensibles à la casse lorsque la colonne utilise un classement qui se termine par _csou _bin(comme les classements utf8_unicode_cset utf8_bin).

Vérifier le classement

Vous pouvez vérifier votre serveur , votre base de données et vos classements de connexion en utilisant:

mysql> show variables like '%collation%';
+----------------------+-------------------+
| Variable_name        | Value             |
+----------------------+-------------------+
| collation_connection | utf8_general_ci   |
| collation_database   | latin1_swedish_ci |
| collation_server     | latin1_swedish_ci |
+----------------------+-------------------+

et vous pouvez vérifier le classement de votre table en utilisant:

mysql> SELECT table_schema, table_name, table_collation 
       FROM information_schema.tables WHERE table_name = `mytable`;
+----------------------+------------+-------------------+
| table_schema         | table_name | table_collation   |
+----------------------+------------+-------------------+
| myschema             | mytable    | latin1_swedish_ci |

Modifier le classement

Vous pouvez modifier le classement de votre base de données, table ou colonne en quelque chose de sensible à la casse comme suit:

-- Change database collation
ALTER DATABASE `databasename` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;

-- or change table collation
ALTER TABLE `table` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;

-- or change column collation
ALTER TABLE `table` CHANGE `Value` 
    `Value` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin;

Vos comparaisons doivent désormais être sensibles à la casse.


25

La comparaison de chaînes dans la phrase WHERE n'est pas sensible à la casse. Vous pouvez essayer de comparer en utilisant

WHERE `colname` = 'keyword'

ou

WHERE `colname` = 'KeyWord'

et vous obtiendrez le même résultat . C'est le comportement par défaut de MySQL.

Si vous voulez que la comparaison soit sensible à la casse , vous pouvez ajouter COLLATEcomme ceci:

WHERE `colname` COLLATE latin1_general_cs = 'KeyWord'

Ce SQL donnerait un résultat différent avec celui-ci: WHERE colnameCOLLATE latin1_general_cs = 'keyword'

latin1_general_cs est un classement commun ou par défaut dans la plupart des bases de données.


16

Le classement que vous choisissez définit si vous êtes sensible à la casse ou non.


9

La valeur par défaut est insensible à la casse, mais la prochaine chose la plus importante que vous devriez examiner est la façon dont la table a été créée en premier lieu, car vous pouvez spécifier la sensibilité à la casse lorsque vous créez la table.

Le script ci-dessous crée une table. Remarquez en bas, il est écrit "COLLATE latin1_general_cs". Que cs à la fin signifie sensible à la casse. Si vous vouliez que votre table soit insensible à la casse, vous devez soit laisser cette partie ou utiliser "COLLATE latin1_general_ci".

   CREATE Table PEOPLE (

       USER_ID  INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,

       FIRST_NAME  VARCHAR(50) NOT NULL,
       LAST_NAME  VARCHAR(50) NOT NULL,

       PRIMARY KEY (USER_ID)

   )

   ENGINE=MyISAM DEFAULT CHARACTER SET latin1
    COLLATE latin1_general_cs AUTO_INCREMENT=0;

Si votre projet est tel que vous pouvez créer votre propre table, il est logique de spécifier votre préférence de respect de la casse lorsque vous créez la table.




2

Notez également que les noms de table sont sensibles à la casse sous Linux, sauf si vous définissez la lower_case_table_namedirective config sur 1 . En effet, les tables sont représentées par des fichiers sensibles à la casse sous Linux.

Méfiez-vous particulièrement du développement sur Windows qui n'est pas sensible à la casse et du déploiement en production où il se trouve. Par exemple:

"SELECT * from mytable" 

contre la table myTable réussira sous Windows mais échouera sous Linux, encore une fois, à moins que la directive susmentionnée ne soit définie.

Référence ici: http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html


1
+1 - Le scénario d'écrire des requêtes insensibles à la casse puis d'échouer sur Linux s'est produit beaucoup dans notre projet
Vic

@Vic J'ai le même problème avec mon projet. Pourriez-vous s'il vous plaît me dire comment avez-vous résolu le problème?
Kamran Ahmed

@KamranAhmed, vous devez utiliser la casse des noms de table exactement tels qu'ils apparaissent dans les scripts de création
Vic

@Vic, ce serait le dernier recours, car je devrais modifier littéralement des tonnes de requêtes. Je me demandais s'il y aurait un moyen facile de le faire. Merci quand même!
Kamran Ahmed

@KamranAhmed, essayez de changer le lower_case_table_namecomme spécifié dans la réponse sous laquelle nous commentons
Vic

1

La solution actuellement acceptée est généralement correcte.

Si vous utilisez une chaîne non binaire (CHAR, VARCHAR, TEXT), les comparaisons ne respectent pas la casse , selon le classement par défaut.

Si vous utilisez une chaîne binaire (BINARY, VARBINARY, BLOB), les comparaisons sont sensibles à la casse, vous devrez donc les utiliser LOWERcomme décrit dans d'autres réponses.

Si vous n'utilisez pas le classement par défaut et que vous utilisez une chaîne non binaire, la sensibilité à la casse est déterminée par le classement choisi.

Source: https://dev.mysql.com/doc/refman/8.0/en/case-sensitivity.html . Lisez attentivement. Certains se sont trompés en disant que les comparaisons sont nécessairement sensibles à la casse ou insensibles. Ce n'est pas le cas.


0

Tu peux l'essayer. j'espère que ce sera utile.

SELECT * FROM `table` WHERE `Value` COLLATE latin1_general_cs = "IAreSavage"

0

Les champs de chaîne avec l'indicateur binaire défini seront toujours sensibles à la casse. Si vous avez besoin d'une recherche sensible à la casse pour un champ de texte non binaire, utilisez ceci: SELECT 'test' REGEXP BINARY 'TEST' AS RESULT;

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.