INT

Los tipos enteros almacenan números sin parte decimal. MySQL ofrece cinco tamaños de enteros, cada uno con un rango y un espacio de almacenamiento diferente. INT (o INTEGER) es el más utilizado y cubre la mayoría de necesidades, pero elegir el tamaño adecuado puede ahorrar espacio en tablas con millones de filas.

Los cinco tipos enteros

TipoBytesRango con signoRango sin signo (UNSIGNED)
TINYINT1-128 a 1270 a 255
SMALLINT2-32,768 a 32,7670 a 65,535
MEDIUMINT3-8,388,608 a 8,388,6070 a 16,777,215
INT4-2,147,483,648 a 2,147,483,6470 a 4,294,967,295
BIGINT8-9.2 × 10^18 a 9.2 × 10^180 a 1.8 × 10^19

INT

INT es el tipo entero estándar. Ocupa 4 bytes y soporta valores desde -2,147 millones hasta +2,147 millones. Es el tipo que usamos en todas las claves primarias de tienda_mysql:

CREATE TABLE ejemplo_int (
    id INT AUTO_INCREMENT PRIMARY KEY,
    cantidad INT NOT NULL,
    posicion INT DEFAULT 0
);
 
INSERT INTO ejemplo_int (cantidad, posicion) VALUES (1500, 3);
INSERT INTO ejemplo_int (cantidad, posicion) VALUES (-200, 1);
INSERT INTO ejemplo_int (cantidad, posicion) VALUES (2147483647, 2);
 
SELECT * FROM ejemplo_int;
idcantidadposicion
115003
2-2001
321474836472

Si intentas insertar un valor fuera de rango:

INSERT INTO ejemplo_int (cantidad) VALUES (2147483648);
ERROR 1264 (22003): Out of range value for column 'cantidad' at row 1

UNSIGNED

El modificador UNSIGNED elimina los valores negativos y duplica el rango positivo:

CREATE TABLE inventario (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    producto VARCHAR(100),
    stock INT UNSIGNED NOT NULL DEFAULT 0,
    vendidos INT UNSIGNED NOT NULL DEFAULT 0
);
 
INSERT INTO inventario (producto, stock, vendidos) VALUES ('Laptop', 50, 120);
 
-- No permite valores negativos
INSERT INTO inventario (producto, stock) VALUES ('Mouse', -5);
ERROR 1264 (22003): Out of range value for column 'stock' at row 1

UNSIGNED es apropiado para columnas que nunca tendrán valores negativos: cantidades, contadores, identificadores. La columna stock de nuestra tabla productos podría ser UNSIGNED, aunque en la práctica usamos la restricción CHECK para el mismo efecto.

TINYINT

TINYINT ocupa solo 1 byte. Es ideal para valores pequeños:

CREATE TABLE configuracion (
    id INT AUTO_INCREMENT PRIMARY KEY,
    clave VARCHAR(50) NOT NULL,
    nivel TINYINT NOT NULL DEFAULT 1,
    activo TINYINT(1) DEFAULT 1
);

MySQL implementa BOOLEAN como TINYINT(1) internamente. Cuando escribes BOOLEAN, MySQL lo almacena como TINYINT(1) donde 0 es FALSE y cualquier otro valor es TRUE.

El rango de TINYINT (-128 a 127, o 0 a 255 con UNSIGNED) es suficiente para edades, puntuaciones del 1 al 5, niveles de prioridad, o cualquier valor acotado.

SMALLINT

SMALLINT ocupa 2 bytes con rango hasta 32,767 (65,535 sin signo):

CREATE TABLE puertos (
    id INT AUTO_INCREMENT PRIMARY KEY,
    servicio VARCHAR(50),
    puerto SMALLINT UNSIGNED NOT NULL
);
 
INSERT INTO puertos (servicio, puerto) VALUES
('HTTP', 80),
('HTTPS', 443),
('MySQL', 3306),
('PostgreSQL', 5432);

Es adecuado para valores que superan el rango de TINYINT pero no necesitan los 4 bytes de INT: números de puerto, códigos de país, identificadores de categoría en catálogos pequeños.

BIGINT

BIGINT ocupa 8 bytes y soporta valores enormes. Es necesario cuando INT no es suficiente:

CREATE TABLE estadisticas_web (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    pagina VARCHAR(200),
    visitas_totales BIGINT UNSIGNED DEFAULT 0,
    bytes_transferidos BIGINT UNSIGNED DEFAULT 0
);
 
INSERT INTO estadisticas_web (pagina, visitas_totales, bytes_transferidos)
VALUES ('/inicio', 5000000000, 12345678901234);

BIGINT es necesario para contadores que pueden superar los 2,147 millones (visitas a páginas web populares, IDs en redes sociales, bytes transferidos), timestamps en milisegundos, o identificadores de sistemas distribuidos.

INT en nuestra base de datos

La tabla productos usa INT para el stock, que tiene valores como 8 (Sofá 3 plazas) hasta 500 (Camiseta algodón):

SELECT nombre, stock FROM productos ORDER BY stock DESC LIMIT 5;
nombrestock
Camiseta algodón básica500
Cable USB-C a Lightning300
Funda iPhone silicona200
Banda elástica set x5200
Camiseta técnica running180

INT es más que suficiente para estos valores. SMALLINT UNSIGNED (hasta 65,535) también bastaría, pero INT es la elección pragmática: 2 bytes extra por fila son insignificantes y evitan problemas futuros si el stock crece.

Ancho de visualización (obsoleto)

En versiones anteriores, INT(11) definía un "ancho de visualización" que indicaba cuántos caracteres se mostraban al usar ZEROFILL. En MySQL 8.0, el ancho de visualización está obsoleto y no afecta al almacenamiento ni al rango:

-- Ambas son equivalentes en MySQL 8.0
CREATE TABLE demo_a (valor INT);
CREATE TABLE demo_b (valor INT(11));

No uses INT(11) en código nuevo. Es confuso porque parece limitar el tamaño pero no lo hace.

Operaciones aritméticas

Los enteros soportan las operaciones aritméticas estándar:

SELECT
    5 + 3 AS suma,
    10 - 7 AS resta,
    4 * 6 AS multiplicacion,
    17 DIV 5 AS division_entera,
    17 MOD 5 AS modulo;
sumarestamultiplicaciondivision_enteramodulo
832432

DIV realiza división entera (descarta el decimal). MOD (o %) devuelve el resto de la división.

Elegir el tipo correcto

Usa TINYINT para valores hasta 127 (o 255 sin signo): booleanos, puntuaciones, niveles. Usa SMALLINT para valores hasta 32,767 (o 65,535): puertos, códigos. Usa INT para la mayoría de los casos: claves primarias, contadores, cantidades. Usa BIGINT solo cuando INT no es suficiente: sistemas de alta escala, contadores masivos.

En caso de duda, usa INT. La diferencia de almacenamiento es mínima y evita sorpresas cuando los datos crecen.

Limpieza

DROP TABLE IF EXISTS ejemplo_int;
DROP TABLE IF EXISTS inventario;
DROP TABLE IF EXISTS configuracion;
DROP TABLE IF EXISTS puertos;
DROP TABLE IF EXISTS estadisticas_web;
DROP TABLE IF EXISTS demo_a;
DROP TABLE IF EXISTS demo_b;

En el siguiente artículo veremos DECIMAL, el tipo ideal para valores monetarios y cálculos que requieren precisión exacta.

Escrito por Eduardo Lázaro