Je me demande s'il y a un "meilleur" choix pour l'assemblage dans MySQL pour un site Web général où vous n'êtes pas sûr à 100% de ce qui sera entré? Je comprends que tous les encodages doivent être les mêmes, tels que MySQL, Apache, le HTML et tout ce qui se trouve à l'intérieur de PHP.
Dans le passé, j'ai configuré PHP pour qu'il sorte en "UTF-8", mais à quel classement cela correspond-il dans MySQL? Je pense qu'il est l' un des caractères UTF-8 ceux, mais je l' ai utilisé utf8_unicode_ci
, utf8_general_ci
et utf8_bin
avant.
Réponses:
La principale différence est la précision du tri (lors de la comparaison des caractères dans la langue) et les performances. Le seul spécial est utf8_bin qui sert à comparer les caractères au format binaire.
utf8_general_ci
est un peu plus rapide queutf8_unicode_ci
, mais moins précis (pour le tri). Le codage de langue spécifique utf8 (tel queutf8_swedish_ci
) contient des règles de langue supplémentaires qui les rendent les plus précises à trier pour ces langues. La plupart du temps, j'utiliseutf8_unicode_ci
(je préfère la précision aux petites améliorations de performances), sauf si j'ai une bonne raison de préférer une langue spécifique.Vous pouvez en savoir plus sur des jeux de caractères Unicode spécifiques dans le manuel MySQL - http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html
la source
utf8_unicode_*
utf8mb4
etutf8mb4_unicode_520_ci
. Ceux-ci vous donnent le reste du chinois, ainsi qu'un classement amélioré.En fait, vous voudrez probablement utiliser
utf8_unicode_ci
ouutf8_general_ci
.utf8_general_ci
trie en supprimant tous les accents et en les triant comme si c'était ASCIIutf8_unicode_ci
utilise l'ordre de tri Unicode, donc il trie correctement dans plus de languesCependant, si vous ne l'utilisez que pour stocker du texte anglais, cela ne devrait pas différer.
la source
Soyez très, très conscient de ce problème qui peut survenir lors de l'utilisation
utf8_general_ci
.MySQL ne fera pas de distinction entre certains caractères dans les instructions select, si le
utf8_general_ci
classement est utilisé. Cela peut conduire à des bugs très désagréables - en particulier par exemple, lorsque les noms d'utilisateur sont impliqués. Selon l'implémentation qui utilise les tables de base de données, ce problème peut permettre à des utilisateurs malveillants de créer un nom d'utilisateur correspondant à un compte administrateur.Ce problème s'expose au moins dans les premières versions 5.x - je ne sais pas si ce comportement a changé plus tard.
Je ne suis pas un administrateur de base de données, mais pour éviter ce problème, j'y vais toujours au
utf8-bin
lieu d'un insensible à la casse.Le script ci-dessous décrit le problème par l'exemple.
la source
'value'
et'valUe'
. L'intérêt d'un classement est qu'il fournit des règles (entre autres) lorsque deux chaînes sont considérées comme égales l'une à l'autre.Il est préférable d'utiliser le jeu de caractères
utf8mb4
avec le classementutf8mb4_unicode_ci
.Le jeu de caractères
utf8
, ne prend en charge qu'une petite quantité de points de code UTF-8, soit environ 6% des caractères possibles.utf8
prend uniquement en charge le plan multilingue de base (BMP). Il y a 16 autres avions. Chaque avion contient 65 536 caractères.utf8mb4
prend en charge les 17 avions.MySQL tronquera les caractères UTF-8 de 4 octets résultant en des données corrompues.
Le
utf8mb4
jeu de caractères a été introduit dans MySQL 5.5.3 le 24/03/2010.Certaines des modifications requises pour utiliser le nouveau jeu de caractères ne sont pas anodines:
ROW_FORMAT=DYNAMIC
REMARQUE: le passage à
Barracuda
deAntelope
peut nécessiter le redémarrage du service MySQL plusieurs fois.innodb_file_format_max
ne change pas avant le service MySQL a été redémarré à:innodb_file_format = barracuda
.MySQL utilise l'ancien
Antelope
format de fichier InnoDB.Barracuda
prend en charge les formats de ligne dynamiques, dont vous aurez besoin si vous ne voulez pas frapper les erreurs SQL pour créer des index et des clés après avoir basculé sur le jeu de caractères:utf8mb4
Le scénario suivant a été testé sur MySQL 5.6.17: Par défaut, MySQL est configuré comme ceci:
Arrêtez votre service MySQL et ajoutez les options à votre my.cnf existant:
Exemple d'instruction SQL CREATE:
INDEX contact_idx (contact)
siROW_FORMAT=DYNAMIC
est supprimée de l'instruction CREATE.REMARQUE: la modification de l'index pour limiter aux 128 premiers caractères sur
contact
élimine la nécessité d'utiliser Barracuda avecROW_FORMAT=DYNAMIC
Notez également: quand il est dit que la taille du champ est de
VARCHAR(128)
128 octets. Vous pouvez utiliser 128 caractères de 4 octets ou 128 caractères de 1 octet.Cette
INSERT
instruction doit contenir le caractère «poo» de 4 octets sur la ligne 2:Vous pouvez voir la quantité d'espace utilisée par la
last
colonne:Dans votre adaptateur de base de données, vous souhaiterez peut-être définir le jeu de caractères et le classement pour votre connexion:
En PHP, cela serait défini pour:
\PDO::MYSQL_ATTR_INIT_COMMAND
Références:
la source
utf8mb4_unicode_520_ci
c'est mieux. À l'avenir, il y en aurautf8mb4_unicode_800_ci
(ou quelque chose comme ça), car MySQL rattrapera les normes Unicode.Les classements affectent la façon dont les données sont triées et la façon dont les chaînes sont comparées les unes aux autres. Cela signifie que vous devez utiliser le classement attendu par la plupart de vos utilisateurs.
Exemple tiré de la documentation de charset unicode :
Donc - cela dépend de votre base d'utilisateurs attendus et de combien vous avez besoin d' un tri correct . Pour une base d'utilisateurs en anglais, cela
utf8_general_ci
devrait suffire, pour d'autres langues, comme le suédois, des classements spéciaux ont été créés.la source
Essentiellement, cela dépend de la façon dont vous pensez d'une chaîne.
J'utilise toujours utf8_bin à cause du problème mis en évidence par Guus. À mon avis, en ce qui concerne la base de données, une chaîne n'est encore qu'une chaîne. Une chaîne est un nombre de caractères UTF-8. Un personnage a une représentation binaire, alors pourquoi a-t-il besoin de connaître la langue que vous utilisez? Habituellement, les gens construiront des bases de données pour des systèmes ayant la portée de sites multilingues. C'est tout l'intérêt d'utiliser UTF-8 comme jeu de caractères. Je suis un peu puriste, mais je pense que les risques de bogues l'emportent largement sur le léger avantage que vous pouvez obtenir sur l'indexation. Toutes les règles liées au langage doivent être effectuées à un niveau beaucoup plus élevé que le SGBD.
Dans mes livres, la «valeur» ne devrait jamais, dans un million d'années, être égale à la «valúe».
Si je veux stocker un champ de texte et faire une recherche insensible à la casse, j'utiliserai des fonctions de chaîne MYSQL avec des fonctions PHP telles que LOWER () et la fonction php strtolower ().
la source
Pour les informations textuelles UTF-8, vous devez utiliser
utf8_general_ci
car ...utf8_bin
: comparer les chaînes par la valeur binaire de chaque caractère de la chaîneutf8_general_ci
: comparer des chaînes en utilisant des règles de langage générales et en utilisant des comparaisons insensibles à la cassealias cela devrait rendre la recherche et l'indexation des données plus rapides / plus efficaces / plus utiles.
la source
La réponse acceptée suggère assez définitivement d'utiliser utf8_unicode_ci, et bien que pour de nouveaux projets c'est génial, je voulais raconter ma récente expérience contraire au cas où cela ferait gagner du temps à quelqu'un.
Parce que utf8_general_ci est le classement par défaut pour Unicode dans MySQL, si vous souhaitez utiliser utf8_unicode_ci, vous finissez par devoir le spécifier à de nombreux endroits.
Par exemple, toutes les connexions client ont non seulement un jeu de caractères par défaut (c'est logique pour moi) mais aussi un classement par défaut (c'est-à-dire que le classement sera toujours par défaut utf8_general_ci pour unicode).
Probablement, si vous utilisez utf8_unicode_ci pour vos champs, vos scripts qui se connectent à la base de données devront être mis à jour pour mentionner explicitement le classement souhaité - sinon les requêtes utilisant des chaînes de texte peuvent échouer lorsque votre connexion utilise le classement par défaut.
Le résultat est que lors de la conversion d'un système existant de n'importe quelle taille en Unicode / utf8, vous pouvez finir par être obligé d'utiliser utf8_general_ci en raison de la façon dont MySQL gère les valeurs par défaut.
la source
Pour le cas mis en évidence par Guus, je suggérerais fortement d'utiliser soit utf8_unicode_cs (sensible à la casse, correspondance stricte, ordre correct pour la plupart) au lieu de utf8_bin (correspondance stricte, ordre incorrect).
Si le champ est destiné à être recherché, par opposition à une correspondance pour un utilisateur, utilisez alors utf8_general_ci ou utf8_unicode_ci. Les deux sont insensibles à la casse, l'un correspondra à tort («ß» est égal à «s» et non à «ss»). Il existe également des versions spécifiques à la langue, comme utf8_german_ci, où la perte de correspondance est plus adaptée à la langue spécifiée.
[Modifier - près de 6 ans plus tard]
Je ne recommande plus le jeu de caractères "utf8" sur MySQL, et je recommande plutôt le jeu de caractères "utf8mb4". Ils correspondent presque entièrement, mais permettent un peu (beaucoup) plus de caractères Unicode.
De manière réaliste, MySQL aurait dû mettre à jour le jeu de caractères "utf8" et les classements respectifs pour correspondre à la spécification "utf8", mais à la place, un jeu de caractères séparé et des classements respectifs pour ne pas affecter la désignation de stockage pour ceux qui utilisent déjà leur jeu de caractères "utf8" incomplet .
la source
utf8_unicode_cs
n'existe pas. Le seul utf8 sensible à la casse estutf8_bin
. Le problème est que leutf8_bin
tri est incorrect. Voir: stackoverflow.com/questions/15218077/…J'ai trouvé ces tableaux de classement utiles. http://collation-charts.org/mysql60/ . Je ne sais pas vraiment quel est l'utf8_general_ci utilisé.
Par exemple, voici le graphique de utf8_swedish_ci. Il montre quels caractères il interprète comme les mêmes. http://collation-charts.org/mysql60/mysql604.utf8_swedish_ci.html
la source
Dans votre fichier de téléchargement de base de données, ajoutez la ligne de suivi avant toute ligne:
Et votre problème devrait être résolu.
la source
SET NAMES
directe d' une requête ne permet pas au client de connaître l'encodage et peut briser certaines fonctionnalités telles que les instructions préparées de manière très subtile.