CHARACTER SET y COLLATION En MySQL

url:http://www.stan.com.mx/topics/view/12
Date: 4 de junio de 2008 a las 1:40

Si tienes dudas sobre qué es un conjunto de caracteres (CHARACTER SET) o una colación (COLLATION) debes empezar leyendo Character Sets and Collations in General.

UTF8 vs Latin1

El latin1 es una codificación de 8 bits de longitud, el utf8 es una codificación de 8 o 16 o 24 bits de longitud. Obviamente el utf8 soporta una mayor cantidad de caracteres internacionales.

img/MySQLCharsetCollationI.gif

Ejemplo con una tabla latin 1:

CREATE TABLE ejemplolatin1 (
  x varchar(10)
) CHARACTER SET='latin1';

INSERT INTO ejemplolatin1 VALUES ('pais');
INSERT INTO ejemplolatin1 VALUES ('país');

Como resultado tenemos palabras de 4 bytes:

SELECT x, LENGTH(x), CHAR_LENGTH(x), HEX(x) FROM ejemplolatin1;

-- 'pais', 4, 4, '70616973'
-- 'país', 4, 4, '7061ED73'

Lo mismo pero con una tabla utf8:

CREATE TABLE ejemploutf8 (
  x varchar(10)
) CHARACTER SET='utf8';

INSERT INTO ejemploutf8 VALUES ('pais');
INSERT INTO ejemploutf8 VALUES ('país');

Ahora tenemos como resultado palabras de 4 y 5 bytes:

SELECT x, LENGTH(x), CHAR_LENGTH(x), HEX(x) FROM ejemploutf8;

-- 'pais', 4, 4, '70616973'
-- 'país', 5, 4, '7061C3AD73'

La función HEX() nos devuelve la cadena en hexadecimal. Podemos ver en la palabra país los valores en hexadecimal de í en latin1 y utf8 respectivamente.

UTF8 A Latin1 Y Viceversa

Para convertir entre codificaciones, tenemos que escribir _utf8 o _latin1 a cualquier cadena o expresión que represente una cadena:

SELECT _utf8'país', _latin1'país';

utf8_spanish_ci vs utf8_general_ci

img/MySQLCharsetCollationN.gif

Las siguientes comparaciones dan verdadero:

SELECT 'a' = 'A' COLLATE utf8_spanish_ci; -- 1
SELECT 'a' = 'á' COLLATE utf8_spanish_ci; -- 1
SELECT 'a' = 'à' COLLATE utf8_spanish_ci; -- 1
SELECT 'a' = 'ä' COLLATE utf8_spanish_ci; -- 1
SELECT 'a' = 'â' COLLATE utf8_spanish_ci; -- 1

Y también estas:

SELECT 'a' = 'A' COLLATE utf8_general_ci; -- 1
SELECT 'a' = 'á' COLLATE utf8_general_ci; -- 1
SELECT 'a' = 'à' COLLATE utf8_general_ci; -- 1
SELECT 'a' = 'ä' COLLATE utf8_general_ci; -- 1
SELECT 'a' = 'â' COLLATE utf8_general_ci; -- 1

Pero la siguente comparación da falso:

SELECT 'n' = 'ñ' COLLATE utf8_spanish_ci; -- 0

En español moderno n no es igual a ñ. Cosa que si sucede en utf8_general_ci:

SELECT 'n' = 'ñ' COLLATE utf8_general_ci; -- 1

utf8_spanish_ci vs utf8_spanish2_ci

Antes del año 1994, ch y ll se consideraban letras independientes, entonces utf8_spanish2_ci (español tradicional) ordena ch entre c y d y ll entre l y m, cosa que no sucede con utf8_spanish_ci (español moderno):

CREATE TABLE ejemploSpanish (
  x varchar(10)
) CHARACTER SET='utf8';

INSERT INTO ejemploSpanish VALUES ('culebra');
INSERT INTO ejemploSpanish VALUES ('chuleta');
INSERT INTO ejemploSpanish VALUES ('luchador');
INSERT INTO ejemploSpanish VALUES ('llanta');
img/MySQLCharsetCollationEs.gif
SELECT * FROM ejemploSpanish ORDER BY x COLLATE utf8_spanish_ci;

-- 'chuleta'
-- 'culebra'
-- 'llanta'
-- 'luchador'
img/MySQLCharsetCollationEs2.gif
SELECT * FROM ejemploSpanish ORDER BY x COLLATE utf8_spanish2_ci;

-- 'culebra'
-- 'chuleta'
-- 'luchador'
-- 'llanta'

Algo similar sucede con el idioma checo (utf8_czech_ci) que considera ch una letra entre h e i.

img/MySQLCharsetCollationCz.gif
CREATE TABLE ejemploCzech (
  x varchar(10)
) CHARACTER SET='utf8';

INSERT INTO ejemploCzech VALUES ('c');
INSERT INTO ejemploCzech VALUES ('h');
INSERT INTO ejemploCzech VALUES ('ch');
INSERT INTO ejemploCzech VALUES ('i');

SELECT * FROM ejemploCzech ORDER BY x COLLATE utf8_czech_ci;

-- 'c'
-- 'h'
-- 'ch'
-- 'i'

utf8_general_ci vs utf8_bin

img/MySQLCharsetCollationBin.gif

Como vimos en los ejemplos de arriba, la colación utf8_spanish_ci no distingue entre:

  • vocales con tilde (acento ortográfico) o sin tilde
  • letras con diéresis o sin diéresis
  • minúsculas y mayúsculas

La colación utf8_bin sí lo hace. Esta colación realiza una comparación binaria, bit por bit:

SELECT 'a' = 'A' COLLATE utf8_general_ci; -- 1
SELECT 'a' = 'á' COLLATE utf8_general_ci; -- 1
SELECT 'a' = 'à' COLLATE utf8_general_ci; -- 1
SELECT 'a' = 'ä' COLLATE utf8_general_ci; -- 1
SELECT 'a' = 'â' COLLATE utf8_general_ci; -- 1


SELECT 'a' = 'A' COLLATE utf8_bin; -- 0
SELECT 'a' = 'á' COLLATE utf8_bin; -- 0
SELECT 'a' = 'à' COLLATE utf8_bin; -- 0
SELECT 'a' = 'ä' COLLATE utf8_bin; -- 0
SELECT 'a' = 'â' COLLATE utf8_bin; -- 0

SHOW CHARACTER SET y SHOW COLLATION

La sentencia SHOW CHARACTER SET despliega todos los conjuntos de caracteres o codificaciones disponibles en el manejador MySQL:

SHOW CHARACTER SET;

La sentencia SHOW COLLATION despliega las diferentes colaciones disponibles en el manejador MySQL:

SHOW COLLATION;

Para conocer las codificaciones usadas actualmente por MySQl, la siguiente consulta puede ayudar:

SHOW VARIABLES LIKE '%char%';

-- 'character_set_client', 'utf8'
-- 'character_set_connection', 'utf8'
-- 'character_set_database', 'latin1'
-- 'character_set_results', 'utf8'
-- 'character_set_server', 'latin1'
-- 'character_set_system', 'utf8'
-- 'character_sets_dir', 'C:\mysql\share\charsets\'

Advertencia

La información de esta página no es confiable. El conocimiento se adquirió de forma empírica (o por fuerza bruta) y algunos términos pudieron ser inventados. Los trucos mencionados en este blog difícilmente son la manera más eficiente de resolver algún problema. La información no se actualiza y tampoco proviene de fuentes oficiales. Mejor acérquese a la documentación oficial, compre libros o visite la Wikipedia.