Diseño de tablas · Referencia práctica

Tipos de datos SQL: cómo elegir el correcto

Una guía para decidir qué guardar en cada columna y qué cambia entre PostgreSQL, MySQL, SQL Server y SQLite.

Actualizado: 28 septiembre 2026Ejemplo comprobado en SQLite
Contenido de esta guía

Qué son los tipos de datos SQL

El tipo de dato indica qué valores espera una columna: enteros, texto, fechas o cantidades con decimales, por ejemplo. Elegirlo bien ayuda a conservar el significado del dato, aplicar restricciones y evitar conversiones o cálculos inesperados. Los nombres y el comportamiento exacto dependen del motor de base de datos.

Respuesta rápida: usa enteros para cantidades sin fracción; DECIMAL(p,s) o NUMERIC(p,s) para importes exactos en PostgreSQL, MySQL y SQL Server; un tipo de texto para nombres; y tipos de fecha y hora propios del motor cuando tengas que compararlas o calcular con ellas. En SQLite, considera guardar el dinero en céntimos enteros, porque declarar DECIMAL no garantiza aritmética decimal exacta.

Cómo elegir el tipo según el dato

Empieza con tres preguntas: ¿puede tener fracción?, ¿qué rango y precisión necesita?, ¿el dato es texto, una fecha o una cantidad? Después comprueba las reglas del motor en producción. Esta tabla sirve como punto de partida, no como sustituto de esas reglas.

Tipo recomendado según el uso
DatoTipo habitualDecisión importante
Unidades, edad, identificadorINTEGER o equivalenteElige un rango suficiente. Un identificador no debe tratarse como número para hacer cálculos.
Precio o importeDECIMAL(p,s) / NUMERIC(p,s)p es el total de dígitos y s los decimales. En SQLite, valora céntimos enteros.
Medición aproximadaFLOAT, REAL o equivalenteAdmite error de representación: evita igualdad exacta y dinero.
Nombre, título, descripciónVARCHAR(n), NVARCHAR(n) o TEXTLa longitud y el soporte Unicode varían por motor y configuración.
Fecha de nacimientoDATENo añadas hora si no existe en el dato.
Instante de un eventoTipo de fecha y hora con zona o convención UTCDefine cómo se interpretará la zona horaria al guardar y leer.
Sí / noBOOLEAN, BIT o entero controladoComprueba la representación y limita los valores válidos.

Precisión: DECIMAL frente a FLOAT

DECIMAL(10,2) permite hasta diez dígitos en total, dos de ellos a la derecha del separador decimal. Es una elección habitual para importes en motores con decimal exacto. FLOAT y REAL representan números aproximados; son útiles para mediciones, pero una suma puede mostrar una pequeña diferencia respecto del decimal esperado. En SQLite, DECIMAL(10,2) tiene afinidad NUMERIC y no equivale a un decimal fijo exacto como en los otros motores citados.

Longitud: VARCHAR, NVARCHAR y TEXT

Si el dato tiene una longitud máxima de negocio, documéntala y valídala. VARCHAR(80) no significa lo mismo en todos los motores: SQLite no hace cumplir ese límite. En SQL Server, NVARCHAR es una opción Unicode y su parámetro n mide pares de bytes, no siempre caracteres visibles. PostgreSQL y MySQL también ofrecen opciones de texto de longitud variable, con diferencias de límites y almacenamiento. No escojas un tipo solo por el nombre parecido.

Fechas, horas y booleanos

Una fecha sin hora es distinta de un instante. PostgreSQL ofrece DATE y TIMESTAMP WITH TIME ZONE; SQL Server ofrece date y datetimeoffset; MySQL ofrece DATE, DATETIME y TIMESTAMP. Define la zona horaria y la forma de presentarla antes de migrar datos. Para banderas, PostgreSQL tiene boolean, MySQL trata BOOLEAN como sinónimo de TINYINT(1) y SQL Server usa bit. SQLite carece de tipos nativos de fecha y booleano: suele guardar fechas como texto ISO 8601 o números, y banderas como 0 y 1.

Comparativa rápida: PostgreSQL, MySQL, SQL Server y SQLite

Equivalencias orientativas; consulta la documentación de tu versión
NecesidadPostgreSQLMySQLSQL ServerSQLite
EnterointegerINTintINTEGER
Dinero exactonumeric(10,2)DECIMAL(10,2)decimal(10,2)INTEGER en céntimos
Texto cortovarchar(80)VARCHAR(80)nvarchar(80)TEXT con CHECK si hace falta límite
FechadateDATEdateTEXT ISO 8601, validado
BanderabooleanBOOLEAN (alias)bitINTEGER con CHECK

La tabla compara intenciones, no declaraciones intercambiables. En particular, una migración desde SQLite necesita revisar validaciones, precisión y fechas. En SQL Server, también existe soporte Unicode con VARCHAR bajo intercalaciones UTF-8; la elección entre VARCHAR y NVARCHAR depende de la configuración y del caso.

Ejemplo comprobado en SQLite

Este ejemplo guarda importes en céntimos para que sumas y filtros usen enteros. Aplica restricciones explícitas al título y a la bandera. La fecha se guarda como texto ISO 8601: la aplicación debe validar que represente una fecha real.

Crear, insertar y consultar
CREATE TABLE productos_tipos_demo (
  id INTEGER PRIMARY KEY,
  nombre TEXT NOT NULL CHECK (length(nombre) BETWEEN 1 AND 80),
  precio_centimos INTEGER NOT NULL CHECK (precio_centimos >= 0),
  activo INTEGER NOT NULL CHECK (activo IN (0, 1)),
  creado_en TEXT NOT NULL
);

INSERT INTO productos_tipos_demo
  (id, nombre, precio_centimos, activo, creado_en)
VALUES (1, 'Cuaderno', 1295, 1, '2026-09-28');

SELECT nombre, precio_centimos, activo
FROM productos_tipos_demo
WHERE precio_centimos >= 1000;
Resultado de la consulta en SQLite
nombreprecio_centimosactivo
Cuaderno12951

El valor 1295 equivale a 12,95 € si la moneda usa dos decimales. Guarda también la divisa si tu aplicación admite más de una; no todas tienen dos decimales. Puedes probar la consulta en el editor SQL del sitio.

Errores frecuentes al elegir tipos de datos

  • Guardar importes en FLOAT: una representación aproximada puede alterar comparaciones y sumas. Usa decimal exacto donde exista o unidades menores enteras si el modelo lo permite.
  • Suponer que VARCHAR(n) siempre limita: en SQLite la longitud indicada no se impone; añade una restricción CHECK o valida en la aplicación.
  • Guardar fechas como texto sin formato definido: formatos mezclados complican ordenar y filtrar. Usa un tipo de fecha nativo cuando exista; en SQLite acuerda un formato ISO 8601 y valida el valor.
  • Confundir NULL con falso o cero: NULL indica ausencia de dato. Usa NOT NULL cuando la columna sea obligatoria y consulta la guía de IS NULL e IS NOT NULL.
  • Copiar la misma declaración entre motores: prueba rangos, Unicode, zonas horarias y restricciones antes de migrar. Un nombre de tipo similar no garantiza el mismo comportamiento.

Qué debes recordar

  • El tipo depende del significado y del rango real del dato.
  • Para dinero, prioriza precisión exacta; evita FLOAT.
  • Texto, fechas y booleanos cambian de comportamiento entre motores.
  • En SQLite, apoya los tipos con CHECK y validación cuando haga falta.

Continúa aprendiendo

Fuentes técnicas consultadas