74981 VISITAS ACERCA ARCHIVOS BLOG FOTOS PROYECTOS

CHARACTER SET y COLLATION En MySQL

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.

utf8 vs latin1

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


utf8_spanish_ci vs utf8_general_ci

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');

utf8_spanish_ci

SELECT * FROM ejemploSpanish ORDER BY x COLLATE utf8_spanish_ci;

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

utf8_spanish2_ci

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.

utf8_czech_ci

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


utf8_general_ci vs utf8_bin

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\'

publicado el 4 de junio de 2008 a las 1:40

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.

Comentarios Y Quejas Aquí






Orale no me sabía todas estas cosas, y no pensé que las fuera a usar algún día, pero ya ves la usé :P

Saludos y felicidades por el blog!!

publicado el 20 de junio de 2008 a las 12:27

Hola
Tu articulo esta increible. Una consulta...
Como hago para cambiar estos valores de mysql ?

-- '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\'

Porque yo tengo todo con latin1 y quiero poner todo en utf8

Gracias

publicado el 11 de julio de 2008 a las 8:44

Hola Enrique. En la mayoría de los casos, cuando abres la conexión tendrás que ejecutar consultas como las siguientes:

SET character_set_client = 'utf8';
SET character_set_results = 'utf8';
SET character_set_connection = 'utf8';

Aunque estas tres consultas son equivalentes a:

SET NAMES 'utf8';

publicado el 11 de julio de 2008 a las 20:35