Character Set

Un character set (conjunto de caracteres) define qué caracteres puede almacenar MySQL y cuántos bytes usa para cada uno. Determina la correspondencia entre bytes almacenados y los caracteres que representan. MySQL soporta más de 40 character sets, pero en la práctica utf8mb4 es el estándar recomendado porque soporta todos los caracteres Unicode, incluidos emojis.

Ver character sets disponibles

SHOW CHARACTER SET;

MySQL muestra todos los character sets soportados. Los más relevantes:

CharsetDescripciónBytes/charCollation por defecto
utf8mb4UTF-8 Unicode completo1-4utf8mb4_0900_ai_ci
utf8mb3UTF-8 (solo BMP, 3 bytes)1-3utf8mb3_general_ci
latin1ISO 8859-1 Western European1latin1_swedish_ci
asciiUS ASCII1ascii_general_ci
binaryBinario puro1binary

utf8mb3 (antes llamado utf8) solo soporta caracteres del Basic Multilingual Plane (hasta 3 bytes). No puede almacenar emojis ni algunos caracteres CJK. Desde MySQL 8.0, utf8mb4 es el character set por defecto.

Niveles de configuración

MySQL permite configurar el character set en cuatro niveles, de más general a más específico:

Nivel de servidor

-- Ver el character set del servidor
SHOW VARIABLES LIKE 'character_set_server';
Variable_nameValue
character_set_serverutf8mb4
-- Ver la collation del servidor
SHOW VARIABLES LIKE 'collation_server';
Variable_nameValue
collation_serverutf8mb4_0900_ai_ci

El character set del servidor se configura en el archivo my.cnf o my.ini:

-- En el archivo de configuración:
-- [mysqld]
-- character-set-server=utf8mb4
-- collation-server=utf8mb4_0900_ai_ci

Nivel de base de datos

Cada base de datos puede tener su propio character set. Si no se especifica, hereda el del servidor:

CREATE DATABASE mi_db CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
-- Ver el character set de una base de datos
SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME = 'tienda_mysql';
DEFAULT_CHARACTER_SET_NAMEDEFAULT_COLLATION_NAME
utf8mb4utf8mb4_0900_ai_ci
-- Cambiar el character set de una base de datos existente
ALTER DATABASE mi_db CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;

Cambiar el character set de una base de datos solo afecta a las tablas que se creen después del cambio. Las tablas existentes mantienen su character set original.

Nivel de tabla

CREATE TABLE mi_tabla (
    id INT PRIMARY KEY,
    nombre VARCHAR(100)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
-- Ver character set de las tablas de tienda_mysql
SELECT TABLE_NAME, TABLE_COLLATION
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'tienda_mysql'
ORDER BY TABLE_NAME;
TABLE_NAMETABLE_COLLATION
categoriasutf8mb4_0900_ai_ci
clientesutf8mb4_0900_ai_ci
detalle_pedidosutf8mb4_0900_ai_ci
empleadosutf8mb4_0900_ai_ci
etiquetas_productoutf8mb4_0900_ai_ci
pedidosutf8mb4_0900_ai_ci
productosutf8mb4_0900_ai_ci
resenasutf8mb4_0900_ai_ci

Nivel de columna

Puedes especificar un character set diferente para columnas individuales:

CREATE TABLE multi_charset (
    id INT PRIMARY KEY,
    nombre VARCHAR(100) CHARACTER SET utf8mb4,
    codigo VARCHAR(20) CHARACTER SET ascii,
    descripcion TEXT CHARACTER SET utf8mb4
);

Usar ascii para columnas que solo contendrán caracteres ASCII (como códigos, identificadores) ahorra espacio porque cada carácter ocupa exactamente 1 byte.

Herencia de character set

Si no especificas un character set, se hereda del nivel superior:

NivelHereda de
ColumnaTabla
TablaBase de datos
Base de datosServidor

utf8mb4 vs utf8mb3

utf8mb3 fue el character set utf8 original de MySQL. Solo soportaba hasta 3 bytes por carácter, lo que excluye muchos caracteres Unicode modernos:

-- Crear tabla con utf8mb3
CREATE TABLE test_charset (
    texto_mb3 VARCHAR(100) CHARACTER SET utf8mb3,
    texto_mb4 VARCHAR(100) CHARACTER SET utf8mb4
);
 
-- Insertar emoji: falla en utf8mb3
-- INSERT INTO test_charset (texto_mb3) VALUES ('Hola 😀');
-- Error: Incorrect string value
 
-- Funciona en utf8mb4
INSERT INTO test_charset (texto_mb4) VALUES ('Hola 😀');
 
SELECT texto_mb4, LENGTH(texto_mb4) AS bytes, CHAR_LENGTH(texto_mb4) AS chars
FROM test_charset;
texto_mb4byteschars
Hola 😀96

El emoji ocupa 4 bytes. LENGTH cuenta bytes, CHAR_LENGTH cuenta caracteres. Con utf8mb4, ambas funciones devuelven valores diferentes para textos con caracteres multibyte.

Característicautf8mb3utf8mb4
Bytes por carácter1-31-4
EmojisNo
Unicode completoNo (solo BMP)
EstadoObsoletoRecomendado
Alias en MySQL 8.0utf8 (deprecated)-

Character set de la conexión

MySQL usa tres variables para la conexión cliente-servidor:

SHOW VARIABLES LIKE 'character_set_%';
Variable_nameValue
character_set_clientutf8mb4
character_set_connectionutf8mb4
character_set_databaseutf8mb4
character_set_resultsutf8mb4
character_set_serverutf8mb4
character_set_systemutf8mb3
  • character_set_client: character set del texto que envía el cliente
  • character_set_connection: character set usado para procesar las consultas
  • character_set_results: character set del texto que devuelve el servidor

Para configurar los tres a la vez:

SET NAMES utf8mb4;
-- Equivale a:
-- SET character_set_client = utf8mb4;
-- SET character_set_connection = utf8mb4;
-- SET character_set_results = utf8mb4;

Funciones de character set

-- Ver el character set de un string
SELECT CHARSET('Hola') AS charset_texto;
charset_texto
utf8mb4
-- Convertir entre character sets
SELECT CONVERT('Hola' USING latin1) AS convertido;
 
-- Ver el character set resultante
SELECT CHARSET(CONVERT('Hola' USING latin1)) AS charset_convertido;
charset_convertido
latin1
-- HEX muestra la representación en bytes
SELECT
    HEX('A') AS ascii_char,
    HEX('ñ') AS latin_char,
    HEX('€') AS euro_char,
    HEX('😀') AS emoji_char;
ascii_charlatin_chareuro_charemoji_char
41C3B1E282ACF09F9880

A ocupa 1 byte, ñ ocupa 2 bytes, ocupa 3 bytes y el emoji ocupa 4 bytes en UTF-8.

Verificar character set de columnas

SELECT COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'tienda_mysql'
  AND TABLE_NAME = 'productos'
  AND CHARACTER_SET_NAME IS NOT NULL;
COLUMN_NAMECHARACTER_SET_NAMECOLLATION_NAME
nombreutf8mb4utf8mb4_0900_ai_ci
descripcionutf8mb4utf8mb4_0900_ai_ci

Solo las columnas de tipo cadena tienen character set. Las columnas numéricas, temporales y binarias no lo necesitan.

Recomendaciones

  1. Usa utf8mb4 siempre. Es el character set por defecto en MySQL 8.0 y soporta todos los caracteres Unicode.

  2. Asegúrate de que la conexión use utf8mb4. Configura SET NAMES utf8mb4 o usa el parámetro de conexión en tu driver.

  3. Usa ascii para columnas que solo necesiten caracteres ASCII (códigos de país, moneda, identificadores). Ahorra espacio.

  4. No uses utf8mb3/utf8. Está obsoleto y no soporta emojis ni muchos caracteres Unicode.

Limpieza

DROP TABLE IF EXISTS test_charset;
DROP TABLE IF EXISTS multi_charset;
DROP DATABASE IF EXISTS mi_db;

En el siguiente artículo veremos las collations, que determinan cómo se comparan y ordenan los caracteres dentro de un character set.

Escrito por Eduardo Lázaro