Tipos de Datos en MySQL
Elegir correctamente los tipos de datos en una base de datos afecta el rendimiento, la integridad y la escalabilidad del sistema.
¿Por qué importa el tipo de dato?
- Elegir el tipo correcto ahorra espacio en disco y tiempo en consultas
- Impone restricciones útiles (ej: no introducir texto donde va un número)
- Aumenta la claridad del modelo de datos
- Previene errores extraños al ordenar, filtrar o calcular
Consideraciones clave antes de elegir
-
¿Qué representa el dato?
¿Texto, número, valor booleano, fecha? -
¿Cuánto varía su longitud?
¿Es fijo (como un código postal) o variable (como un comentario)? -
¿Lo vas a comparar, ordenar o agrupar?
Hay collations más o menos adecuadas para cada idioma. -
¿Cuánta precisión necesitas?
Por ejemplo: dinero = exactitud (DECIMAL), estadísticas = rendimiento (FLOAT).
Tipos de datos numéricos
| Tipo | Tamaño típico | Rango (con signo) | Comentario |
|---|---|---|---|
TINYINT |
1 byte | -128 a 127 | Muy compacto |
SMALLINT |
2 bytes | -32,768 a 32,767 | |
INT |
4 bytes | -2 mil millones | Ideal para IDs |
BIGINT |
8 bytes | ±9 cuatrillones | Para facturas o totales grandes |
DECIMAL(10,2) |
depende | Precisión fija para decimales | Usado en dinero |
FLOAT, DOUBLE |
4-8 bytes | Más rápido, menos preciso | Evitar en cálculos críticos |
Nota: DECIMAL guarda dígito a dígito y ofrece exactitud perfecta. FLOAT y DOUBLE usan coma flotante binaria y pueden acumular pequeños errores de redondeo. Para dinero o cantidades donde el centavo importa, usa siempre DECIMAL.
Tipos de cadenas (texto)
| Tipo | Tamaño | Comentario |
|---|---|---|
CHAR(n) |
fijo | Rellena con espacios si es más corto |
VARCHAR(n) |
variable | Longitud real + 1 o 2 bytes extra |
TEXT |
hasta 65 KB | No indexable completamente |
MEDIUMTEXT |
hasta 16 MB | Para posts largos, artículos |
LONGTEXT |
hasta 4 GB | Raramente necesario |
Nota: VARCHAR(255) es una convención extendida, no un límite real. VARCHAR no tiene un tope físico a 255 caracteres; el valor máximo depende del juego de caracteres y del tamaño de fila. Sin embargo, los índices compuestos y la codificación pueden imponer restricciones prácticas.
Tipos de fecha y hora
| Tipo | Formato | Comentario |
|---|---|---|
DATE |
YYYY-MM-DD |
Solo fecha |
DATETIME |
YYYY-MM-DD HH:MM:SS |
Sin zona horaria |
TIMESTAMP |
Igual que DATETIME |
Ajusta según huso horario del servidor |
TIME |
HH:MM:SS |
Duraciones o intervalos |
YEAR |
YYYY |
Solo año |
Nota: TIMESTAMP tiene rango limitado: de 1970 a 2038 (el conocido problema del año 2038). DATETIME va de 1000 a 9999 y es preferible cuando necesitas almacenar fechas fuera de ese rango o no quieres conversiones automáticas de zona horaria.
Otros tipos
ENUM('A','B'): valor limitado a una listaSET('x','y','z'): múltiple elección sobre un conjuntoBLOB,MEDIUMBLOB: datos binarios (fotos, adjuntos)BOOLEAN: sinónimo deTINYINT(1)en realidadBIT: permite almacenar n bits exactos en una columna. No es sinónimo deBOOLEAN
Nota: ENUM es cómodo para listas cortas y estables, pero costoso de migrar si los valores cambian con el tiempo. Si las opciones pueden crecer o variar, considera mejor una tabla auxiliar con relación de clave foránea.
Como limitar el contenido de una entrada
El valor en INT(4) no restringe el número de cifras. Solo afecta cómo se presenta si se usa con ZEROFILL:
edad TINYINT UNSIGNED CHECK (edad <= 120)
Texto
Controlar longitud con VARCHAR(n) o CHAR(n)
codigo_postal CHAR(5) CHECK (codigo_postal REGEXP '^[0-9]{5}$')
Casos comunes
| Campo | Tipo de dato recomendado | Validación adicional |
|---|---|---|
| DNI | CHAR(9) |
CHECK (CHAR_LENGTH(dni) = 9) |
| Código Postal | CHAR(5) o CHAR(6) |
REGEXP '^[0-9]{5,6}$' si necesario |
| Teléfono | VARCHAR(15) |
CHECK (telefono REGEXP '^\\+?[0-9]{9,15}$') |
| Contraseña | VARCHAR(72) |
(si usas bcrypt) |
| Edad | TINYINT UNSIGNED |
CHECK (edad BETWEEN 0 AND 120) |
| Precio | DECIMAL(10,2) |
Para precisión con 2 decimales |
Consejos
UNSIGNED: elimina valores negativos y amplía el rango positivoZEROFILL: completa números con ceros a la izquierda (00042)AUTO_INCREMENT: para claves primarias numéricas
Ejemplo: tabla de usuarios
CREATE TABLE usuarios (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(254) NOT NULL,
edad TINYINT UNSIGNED CHECK (edad BETWEEN 13 AND 120),
salario DECIMAL(10,2),
fecha_registro TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
En la próxima lección: aprenderemos a explorar la estructura de una base de datos existente con los comandos SHOW y DESCRIBE.