2010-02-26 12 views
248

Estoy tratando de averiguar qué colación debo usar para varios tipos de datos. El usuario debe enviar el 100% del contenido que almacenaré.UTF-8: General? ¿Compartimiento? Unicode?

Según tengo entendido, debería utilizar UTF-8 General CI (distinción entre mayúsculas y minúsculas) en lugar de UTF-8 binario. Sin embargo, no puedo encontrar una distinción clara entre UTF-8 General CI y UTF-8 Unicode CI.

  1. ¿Debo estar almacenando el contenido enviado por el usuario en columnas UTF-8 General o UTF-8 Unicode CI?
  2. ¿A qué tipo de datos se aplicará UTF-8 Binary?
+9

Nota al margen pero en lugar de 'utf8', use' utf8mb4' en su lugar para soporte completo UTF-8. Comenta aquí porque las respuestas a esta pregunta popular no abordan esto. https://mathiasbynens.be/notes/mysql-utf8mb4 –

+0

Si desea doblar caso, pero la sensibilidad de acento, por favor presente una solicitud en http://bugs.mysql.com. –

+0

O haga clic en "Me afecta" en https://bugs.mysql.com/bug.php?id=58797 y agregue un comentario. –

Respuesta

272

En general, utf8_general_ci es más rápido que utf8_unicode_ci, pero menos correcta.

Aquí está la diferencia:

Para cualquier conjunto de caracteres Unicode, operaciones realizadas mediante el cotejo _general_ci son más rápidos que los de la colación _unicode_ci. Por ejemplo, las comparaciones para la intercalación utf8_general_ci son más rápidas, pero ligeramente menos correctas, que las comparaciones para utf8_unicode_ci. La razón de esto es que utf8_unicode_ci admite asignaciones tales como expansiones; es decir, cuando un personaje se compara como igual a las combinaciones de otros personajes. Por ejemplo, en alemán y en otros idiomas, "ß" es igual a "ss". utf8_unicode_ci también admite contracciones y caracteres ignorables. utf8_general_ci es una clasificación heredada que no admite expansiones, contracciones o caracteres ignorables. Solo puede hacer comparaciones uno a uno entre los personajes.

Citado de: http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html

Para una explicación más detallada, por favor lea el siguiente post de los foros de MySQL: http://forums.mysql.com/read.php?103,187048,188748

En cuanto a utf8_bin: Tanto utf8_general_ci y utf8_unicode_ci realizar caso -Comprensión insensible. En contraste, utf8_bin distingue entre mayúsculas y minúsculas (entre otras diferencias), porque compara los valores binarios de los caracteres.

+2

Creo que si no tiene una buena razón para usar _unicode_ci, entonces use _general_ci. – Sagi

+4

Sin embargo, esto realmente no responde la pregunta en profundidad. * ¿Cuál es la diferencia entre estas intercalaciones exactamente? * –

+3

Tiene razón, la diferencia exacta no se proporciona aquí en aras de la simplicidad. Agregué un enlace a una publicación con la * diferencia * exacta. – Sagi

82

También debe tener en cuenta que con utf8_general_ci cuando se usa un campo varchar como índice único o principal, insertar 2 valores como 'a' y 'á' daría un error de clave duplicada.

+3

Gracias, esto es útil para evitar nombres de usuario similares (por ejemplo, si existe "jose", no me gustaría que alguien más cree un usuario "josé") Nota: esto también es cierto para la mayoría de las intercalaciones utf8 (excepto utf8_bin). El más seguro/más seguro/más completo es 'utf8_unicode_ci' – Costa

+2

Uso utf8_bin donde quiero que se distingan entre jose y josé en el índice. Por ejemplo, una columna que registra operaciones de búsqueda/reemplazo, donde el usuario podría haber decidido buscar josé, y reemplazarlo con jose. (Estoy escribiendo un programa de hoja de cálculo) –

6

Realmente, probé los valores de guardado como 'é' y 'e' en la columna con índice único y causan errores duplicados tanto en 'utf8_unicode_ci' como 'utf8_general_ci'. Puede guardarlos solo en la columna intercalada 'utf8_bin'.

Y los documentos de mysql (en http://dev.mysql.com/doc/refman/5.7/en/charset-applications.html) sugieren en sus ejemplos la intercalación 'utf8_general_ci'.

[mysqld] 
character-set-server=utf8 
collation-server=utf8_general_ci 
+1

Hice una prueba rápida de esto, y parece ser precisa. Ambas intercalaciones se comportan igual cuando se trata de una clave única en una columna y valores con tildes y similares. – MirroredFate

+0

@MirroredFate OK, debería agregar que esa columna debe tener un índice único para causar este error. Implica en mi respuesta. – vitalii

19
  • utf8_bin compara los bits a ciegas. Sin doblar caso, sin acento.
  • utf8_general_ci compara un byte con un byte. Hace casos plegables y stripping de acento, pero no comparaciones de 2 caracteres: ij no es igual a ij en esta intercalación.
  • utf8_*_ci es un conjunto de reglas específicas del idioma, pero por lo demás como unicode_ci. Algunos casos especiales: Ç, Č, ch, ll
  • utf8_unicode_ci sigue un viejo estándar Unicode para las comparaciones. ij = ij, pero ae! = æ
  • utf8_unicode_520_ci sigue un nuevo estándar Unicode. ae = æ

Ver collation chart para obtener más información sobre lo que es igual a lo que en varias colaciones UTF8.

utf8, según la definición de MySQL está limitado a los códigos utf8 de 1 a 3 bytes. Esto deja fuera Emoji y algunos de los chinos. Entonces realmente debería cambiarse a utf8mb4 si quiere ir más allá de Europa.

Los puntos anteriores se aplican a utf8mb4, después de un cambio ortográfico adecuado. En adelante, se prefieren utf8mb4 y utf8mb4_unicode_520_ci.

  • utf16 y utf32 son variantes en utf8; prácticamente no hay uso para ellos.
  • ucs2 está más cerca de "Unicode" que "utf8"; prácticamente no hay uso para eso.
+0

Re "estad atentos": [_8.0 collations_] (http://mysql.rjweb.org/utf8mb4_collations.html) muestra cómo se comparan los distintos caracteres, diptongos, etc. en las intercalaciones de 8,0 utf8mb4; utf8 es casi lo mismo. –

+0

Y las intercalaciones de 8.0 se sincronizan para ser _significativamente_ más rápidas que 5.x. –