Elegir un tipo de dato es como elegir la herramienta para el trabajo. No vas a usar un destornillador para clavar un clavo (eso espero). Pues en la base de datos es igual: el tipo de dato correcto afecta mucho al rendimiento, el ahorro de memoria y la facilidad de manejar los datos. Por ejemplo, si guardamos dinero en formato REAL, podemos tener problemas de precisión, y usar TEXT en vez de VARCHAR para cadenas cortas hace que la base ocupe más memoria.
Cuando elijas el tipo de dato, ten en cuenta varios factores:
Naturaleza de los datos
Define a qué categoría pertenecen los datos: números, cadenas, valores booleanos, fechas o algo más complejo, como estructuras JSON.
Volumen de datos
¿Cuántos datos piensas guardar? Por ejemplo, para textos de hasta 50 caracteres es mejor elegir VARCHAR(50) en vez de TEXT.
Precisión y rango
¿Necesitas mantener alta precisión (por ejemplo, para cálculos financieros)? ¿Quieres limitar el rango de valores?
Frecuencia y tipo de consultas
¿Con qué frecuencia vas a acceder a los datos? Ten en cuenta que los tipos complejos como JSONB requieren más recursos para procesar.
Ejemplos de elección de tipos de datos
Diferentes datos — diferentes tareas. A veces importa la precisión hasta el último céntimo, y a veces solo que todo quepa. Aquí tienes ejemplos de cómo elegir el tipo de dato adecuado para cada situación.
Datos financieros
Cuando se trata de guardar dinero, como en la contabilidad, los errores no se permiten. Así que la mejor opción es el tipo NUMERIC, que da alta precisión. Por ejemplo, queremos una tabla con estas columnas:
| Nombre de columna | Tipo de dato | Comentario |
|---|---|---|
| id | SERIAL | Clave primaria |
| amount | NUMERIC(10, 2) | Diez dígitos, de los cuales dos son decimales |
| currency_code | CHAR(3) | Código ISO de moneda, por ejemplo "USD", "EUR" |
| transaction_date | TIMESTAMP | Fecha de la transacción, por defecto — hora actual |
¿Por qué no REAL? Porque los números de coma flotante pueden perder precisión, y eso es crítico para temas de dinero.
Datos de texto
Si vas a guardar nombres de usuario, direcciones o cualquier otra cadena, siempre pon una longitud máxima cuando puedas. Por ejemplo, VARCHAR(50) en vez de TEXT. Así evitas posibles errores y optimizas la memoria.
| Nombre de columna | Tipo de dato | Comentario |
|---|---|---|
| id | SERIAL | Clave primaria |
| username | VARCHAR(50) | Login del usuario, único y obligatorio |
| VARCHAR(255) | ||
| bio | TEXT | Biografía, puede ser texto largo |
Si la longitud de la cadena es estrictamente fija (por ejemplo, códigos de país de dos letras), usa CHAR:
| Nombre de columna | Tipo de dato | Comentario |
|---|---|---|
| code | CHAR(2) | Código ISO de país (por ejemplo, "US"), clave primaria |
| name | VARCHAR(100) | Nombre del país, obligatorio |
Datos de marcas de tiempo
Para guardar la hora de eventos o agendas normalmente se usa TIMESTAMP, porque tiene fecha y hora a la vez.
| Nombre de columna | Tipo de dato | Comentario |
|---|---|---|
| id | SERIAL | Clave primaria |
| event_name | VARCHAR(100) | Nombre del evento |
| start_time | TIMESTAMP | Hora de inicio del evento, obligatorio |
| end_time | TIMESTAMP | Hora de fin del evento, obligatorio |
Si solo necesitas la hora sin fecha, usa TIME, y si solo la fecha sin hora — DATE.
Identificadores únicos
Cuando necesitas crear identificadores que sean únicos a nivel global, usa UUID. Por ejemplo, para generar un identificador único de transacción:
| Nombre de columna | Tipo de dato | Comentario |
|---|---|---|
| request_id | UUID | Identificador único de la petición, se genera por defecto con gen_random_uuid() |
| endpoint | VARCHAR(255) | Dirección del endpoint de la API llamada |
| timestamp | TIMESTAMP | Hora de la petición, por defecto — hora actual |
JSONB: estructuras complejas
Cuando necesitas guardar datos cuya estructura puede cambiar o ser compleja, por ejemplo, preferencias de usuario o metadatos, usa JSONB.
| Nombre de columna | Tipo de dato | Comentario |
|---|---|---|
| user_id | SERIAL | Clave primaria (ID del usuario) |
| preferences | JSONB | Preferencias del usuario en formato JSON |
Trabajar con JSONB es cómodo, pero ojo que puede bajar el rendimiento si hay muchas inserciones/actualizaciones.
Arrays
Los arrays van bien si necesitas guardar listas de datos homogéneos. Por ejemplo, una lista de etiquetas:
| Nombre de columna | Tipo de dato | Comentario |
|---|---|---|
| id | SERIAL | Clave primaria |
| title | VARCHAR(255) | Título del artículo |
| tags | TEXT[] | Array de etiquetas |
Resumen de tipos de datos por tarea
| Tipo de tarea | Tipo de dato recomendado | Ejemplo |
|---|---|---|
| Identificador de registro | SERIAL, BIGSERIAL, UUID |
id SERIAL PRIMARY KEY |
| Cantidad, números enteros | INTEGER, BIGINT |
quantity INTEGER |
| Cálculos financieros | NUMERIC |
price NUMERIC(10, 2) |
| Almacenamiento de cadenas | VARCHAR(n), TEXT |
username VARCHAR(50) |
| Cadenas cortas y fijas | CHAR(n) |
status CHAR(1) |
| Fechas y horas | DATE, TIME, TIMESTAMP |
created_at TIMESTAMP DEFAULT NOW() |
| Identificadores únicos | UUID |
id UUID PRIMARY KEY DEFAULT gen_random_uuid() |
| Estructuras complejas (JSON) | JSONB |
metadata JSONB |
| Listas de valores | ARRAY |
tags TEXT[] |
| Valor booleano | BOOLEAN |
is_active BOOLEAN |
Seguro que ya conoces todos los tipos menos SERIAL. El caso es que SERIAL es básicamente lo mismo que INTEGER, que se usa como identificador de filas en las tablas.
Se incrementa automáticamente en 1 cuando añades una nueva fila a la tabla. Así, si añades 10 filas, la primera tendrá id igual a 1, la segunda — 2, etc. Más sobre esto lo verás en la próxima lección :)
GO TO FULL VERSION