Collation
Una collation define las reglas para comparar y ordenar caracteres dentro de un character set. Determina si 'a' y 'A' son iguales, si 'ñ' va después de 'n' o después de 'o', y si 'café' y 'cafe' coinciden en una búsqueda. Cada character set tiene una collation por defecto, pero puede tener varias disponibles.
Convenciones de nombres
Las collations siguen un patrón que indica su comportamiento:
charset_idioma_modificadores
Los sufijos indican la sensibilidad:
| Sufijo | Significado | Ejemplo |
|---|---|---|
_ai | Accent Insensitive | 'café' = 'cafe' |
_as | Accent Sensitive | 'café' ≠ 'cafe' |
_ci | Case Insensitive | 'abc' = 'ABC' |
_cs | Case Sensitive | 'abc' ≠ 'ABC' |
_bin | Binario | Compara byte a byte |
_ks | Kana Sensitive | Distingue hiragana/katakana |
Ejemplos de collations comunes:
| Collation | Descripción |
|---|---|
| utf8mb4_0900_ai_ci | Unicode 9.0, case/accent insensitive (defecto MySQL 8.0) |
| utf8mb4_0900_as_cs | Unicode 9.0, case/accent sensitive |
| utf8mb4_general_ci | General, case insensitive (más rápida, menos precisa) |
| utf8mb4_bin | Binaria, compara bytes |
| utf8mb4_spanish_ci | Reglas de ordenamiento español |
Ver collations disponibles
-- Todas las collations para utf8mb4
SHOW COLLATION WHERE Charset = 'utf8mb4';Hay muchas. Para ver solo las más usadas:
SELECT COLLATION_NAME, IS_DEFAULT
FROM information_schema.COLLATIONS
WHERE CHARACTER_SET_NAME = 'utf8mb4'
AND COLLATION_NAME LIKE '%0900%'
ORDER BY COLLATION_NAME
LIMIT 10;| COLLATION_NAME | IS_DEFAULT |
|---|---|
| utf8mb4_0900_ai_ci | Yes |
| utf8mb4_0900_as_ci | |
| utf8mb4_0900_as_cs | |
| utf8mb4_0900_bin |
utf8mb4_0900_ai_ci es la collation por defecto de MySQL 8.0. El 0900 hace referencia a Unicode 9.0.
Efecto en comparaciones
La collation afecta directamente cómo funcionan WHERE, ORDER BY, DISTINCT y los índices:
CREATE TABLE test_collation (
texto VARCHAR(100) COLLATE utf8mb4_0900_ai_ci
);
INSERT INTO test_collation VALUES ('café'), ('Cafe'), ('CAFÉ'), ('cafe');
-- Con collation ai_ci (accent insensitive, case insensitive)
SELECT texto FROM test_collation WHERE texto = 'cafe';| texto |
|---|
| café |
| Cafe |
| CAFÉ |
| cafe |
Las cuatro filas coinciden porque la collation ai_ci ignora mayúsculas y acentos.
-- Comparar con collation as_cs (accent sensitive, case sensitive)
SELECT texto FROM test_collation WHERE texto = 'cafe' COLLATE utf8mb4_0900_as_cs;| texto |
|---|
| cafe |
Solo coincide la escritura exacta.
Efecto en ordenamiento
CREATE TABLE test_orden (
nombre VARCHAR(100) COLLATE utf8mb4_0900_ai_ci
);
INSERT INTO test_orden VALUES ('ñandú'), ('naranja'), ('oliva'), ('nuez');
-- Ordenamiento con collation por defecto
SELECT nombre FROM test_orden ORDER BY nombre;| nombre |
|---|
| naranja |
| nuez |
| ñandú |
| oliva |
Con utf8mb4_0900_ai_ci, la ñ se ordena correctamente entre la n y la o, siguiendo las reglas Unicode.
-- Comparar con collation binaria
SELECT nombre FROM test_orden ORDER BY nombre COLLATE utf8mb4_bin;| nombre |
|---|
| naranja |
| nuez |
| oliva |
| ñandú |
Con la collation binaria, ñ va al final porque su valor en bytes (0xC3B1) es mayor que el de o (0x6F).
Collation español
MySQL incluye una collation específica para español:
CREATE TABLE test_espanol (
palabra VARCHAR(100)
);
INSERT INTO test_espanol VALUES ('carro'), ('casa'), ('chico'), ('cielo');
-- Con collation general
SELECT palabra FROM test_espanol ORDER BY palabra COLLATE utf8mb4_0900_ai_ci;| palabra |
|---|
| carro |
| casa |
| chico |
| cielo |
-- Con collation española tradicional
SELECT palabra FROM test_espanol ORDER BY palabra COLLATE utf8mb4_es_trad_0900_ai_ci;| palabra |
|---|
| carro |
| casa |
| cielo |
| chico |
La collation utf8mb4_es_trad_0900_ai_ci (español tradicional) trata ch como una letra separada que va después de c. La collation estándar la trata como c + h.
| Collation | Tratamiento de ch | Tratamiento de ll |
|---|---|---|
| utf8mb4_0900_ai_ci | c + h (estándar) | l + l (estándar) |
| utf8mb4_es_trad_0900_ai_ci | Letra ch (después de c) | Letra ll (después de l) |
| utf8mb4_spanish_ci | c + h (estándar) | l + l (estándar) |
En la práctica, la mayoría de las aplicaciones en español usan utf8mb4_0900_ai_ci (la collation por defecto), que sigue las reglas de la RAE modernas donde ch y ll no son letras separadas.
Collation en tienda_mysql
SELECT TABLE_NAME, TABLE_COLLATION
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'tienda_mysql';| TABLE_NAME | TABLE_COLLATION |
|---|---|
| categorias | utf8mb4_0900_ai_ci |
| clientes | utf8mb4_0900_ai_ci |
| detalle_pedidos | utf8mb4_0900_ai_ci |
| empleados | utf8mb4_0900_ai_ci |
| etiquetas_producto | utf8mb4_0900_ai_ci |
| pedidos | utf8mb4_0900_ai_ci |
| productos | utf8mb4_0900_ai_ci |
| resenas | utf8mb4_0900_ai_ci |
Todas usan la collation por defecto, lo que significa que las búsquedas en texto son case-insensitive y accent-insensitive:
-- Buscar "maria" encuentra "María"
SELECT nombre, apellidos FROM clientes WHERE nombre = 'maria';| nombre | apellidos |
|---|---|
| María | García López |
-- Buscar sin acento encuentra con acento
SELECT nombre FROM productos WHERE nombre LIKE '%electronica%';Esta consulta no devuelve resultados porque LIKE con la collation ai_ci no ignora acentos dentro de LIKE en todas las versiones. Para búsquedas insensibles a acentos, es mejor usar la collation explícitamente o normalizar los datos.
COLLATE en consultas
Puedes usar COLLATE en cualquier expresión para cambiar la collation temporalmente:
-- Búsqueda case-sensitive
SELECT nombre, precio
FROM productos
WHERE nombre COLLATE utf8mb4_0900_as_cs = 'iphone 15 pro';Esta consulta no devuelve resultados porque el nombre real es iPhone 15 Pro (con mayúsculas).
-- Búsqueda case-sensitive correcta
SELECT nombre, precio
FROM productos
WHERE nombre COLLATE utf8mb4_0900_as_cs = 'iPhone 15 Pro';| nombre | precio |
|---|---|
| iPhone 15 Pro | 1299.99 |
Cambiar collation de una columna
ALTER TABLE mi_tabla
MODIFY nombre VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_cs;Cambiar la collation de una columna con datos existentes puede ser una operación costosa en tablas grandes, ya que MySQL debe reconstruir los índices.
Collation y UNIQUE
La collation afecta las restricciones UNIQUE. Con ai_ci, valores que difieren solo en mayúsculas o acentos se consideran duplicados:
CREATE TABLE test_unique (
email VARCHAR(100) UNIQUE COLLATE utf8mb4_0900_ai_ci
);
INSERT INTO test_unique VALUES ('user@email.com');
-- Esto falla: duplicado por collation ci
-- INSERT INTO test_unique VALUES ('User@Email.com');
-- Error: Duplicate entryEsto es generalmente el comportamiento deseado para emails, pero si necesitas distinguir mayúsculas:
CREATE TABLE test_unique_cs (
codigo VARCHAR(50) UNIQUE COLLATE utf8mb4_0900_as_cs
);
INSERT INTO test_unique_cs VALUES ('abc');
INSERT INTO test_unique_cs VALUES ('ABC');
SELECT * FROM test_unique_cs;| codigo |
|---|
| abc |
| ABC |
Con collation as_cs, 'abc' y 'ABC' son valores diferentes y ambos se aceptan.
Collation y ORDER BY
SELECT nombre, precio
FROM productos
WHERE categoria_id = 6
ORDER BY nombre COLLATE utf8mb4_0900_ai_ci;| nombre | precio |
|---|---|
| Google Pixel 8 | 699.00 |
| iPhone 15 Pro | 1299.99 |
| Samsung Galaxy S24 | 899.99 |
| Xiaomi 14 | 599.99 |
-- Ordenamiento binario (por valor de bytes)
SELECT nombre, precio
FROM productos
WHERE categoria_id = 6
ORDER BY nombre COLLATE utf8mb4_bin;| nombre | precio |
|---|---|
| Google Pixel 8 | 699.00 |
| Samsung Galaxy S24 | 899.99 |
| Xiaomi 14 | 599.99 |
| iPhone 15 Pro | 1299.99 |
Con collation binaria, iPhone va al final porque la i minúscula (0x69) tiene un valor mayor que las mayúsculas G (0x47), S (0x53) y X (0x58).
Recomendaciones
| Caso de uso | Collation recomendada |
|---|---|
| General (por defecto) | utf8mb4_0900_ai_ci |
| Contraseñas, tokens | utf8mb4_bin |
| Nombres de usuario (case-sensitive) | utf8mb4_0900_as_cs |
| Emails (case-insensitive) | utf8mb4_0900_ai_ci |
| Español con ch/ll tradicional | utf8mb4_es_trad_0900_ai_ci |
| Comparaciones exactas | utf8mb4_0900_as_cs o utf8mb4_bin |
Limpieza
DROP TABLE IF EXISTS test_collation;
DROP TABLE IF EXISTS test_orden;
DROP TABLE IF EXISTS test_espanol;
DROP TABLE IF EXISTS test_unique;
DROP TABLE IF EXISTS test_unique_cs;Con esto completamos la sección de conjuntos de caracteres. En la siguiente sección exploraremos los índices en MySQL, una herramienta fundamental para optimizar el rendimiento de las consultas.
Escrito por Eduardo Lázaro
