Saltar al contenido
Bases de datos con SQL
Todos los cursos Ir al ejercicio →

Diseñar tablas

  • ⏱ 60 minutos
  • 📶 Nivel: principiante
  • 🧩 Incluye ejercicio

💡 🎯 Al terminar esta lección podrás…

  • Crear tablas con CREATE TABLE, eligiendo tipos y restricciones.
  • Usar PRIMARY KEY, NOT NULL, UNIQUE, DEFAULT y CHECK.
  • Modificar y eliminar tablas con ALTER TABLE y DROP TABLE.
  • Aplicar la normalización básica: «un dato, un lugar».

1.CREATE TABLE: crear una tabla

Hasta ahora usábamos una tabla ya creada. CREATE TABLE define una nueva: su nombre y, para cada columna, su nombre, su tipo y sus restricciones.

Estructura general
CREATE TABLE nombre_tabla (
  columna1  TIPO  restricciones,
  columna2  TIPO  restricciones,
  ...
);

Un ejemplo completo: la tabla de clientes de la tienda.

Tabla clientes
CREATE TABLE clientes (
  id     INTEGER PRIMARY KEY,
  nombre TEXT    NOT NULL,
  email  TEXT    NOT NULL UNIQUE,
  edad   INTEGER CHECK (edad >= 18),
  pais   TEXT    DEFAULT 'Perú'
);

Lee cada línea como una frase:

Prueba a insertar un cliente indicando solo lo necesario:

Insertar
INSERT INTO clientes (nombre, email, edad)
VALUES ('Ana Torres', 'ana@correo.com', 25);

SELECT * FROM clientes;

Resultado esperado (el país se rellenó solo)

idnombreemailedadpais
1Ana Torresana@correo.com25Perú

📌 Nota · Una columna por cada dato simple

Cada columna guarda un solo dato de un solo tipo. Si te encuentras guardando listas separadas por comas dentro de una celda, es señal de que necesitas otra tabla (más abajo, en normalización).

2.Las restricciones de columna

RestricciónQué garantizaEjemplo
PRIMARY KEYIdentifica la fila: único y nunca vacíoid INTEGER PRIMARY KEY
NOT NULLLa columna siempre debe tener valornombre TEXT NOT NULL
UNIQUENo hay dos filas con el mismo valoremail TEXT UNIQUE
DEFAULTValor que se usa si no se indica ningunopais TEXT DEFAULT 'Perú'
CHECKUna condición que el valor debe cumplirCHECK (precio > 0)
FOREIGN KEYEl valor debe existir en otra tabla (lección 5)REFERENCES clientes(id)

Si una instrucción rompe una restricción, la base de datos la rechaza. Estos son los mensajes reales de SQLite para nuestra tabla clientes:

Email repetido (UNIQUE)
INSERT INTO clientes (nombre, email)
VALUES ('Otra Ana', 'ana@correo.com');
Error en SQLite
UNIQUE constraint failed: clientes.email
Edad no permitida (CHECK)
INSERT INTO clientes (nombre, email, edad)
VALUES ('Luis', 'luis@correo.com', 15);
Error en SQLite
CHECK constraint failed: edad >= 18
Sin nombre (NOT NULL)
INSERT INTO clientes (email)
VALUES ('sin-nombre@correo.com');
Error en SQLite
NOT NULL constraint failed: clientes.nombre

💡 Consejo · Deja que la base de datos valide

Valida también en tu aplicación para dar mensajes amables, pero no confíes solo en eso: las restricciones de la tabla son la última defensa y protegen los datos aunque haya un error en el código o alguien escriba directamente en la base.

Identificadores automáticos

Como vimos, las claves id suelen numerarse solas. La sintaxis depende del motor:

MotorCómo declararlo
SQLiteid INTEGER PRIMARY KEY (se autonumera). Añadir AUTOINCREMENT evita reutilizar ids borrados, pero rara vez hace falta.
PostgreSQLid INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY (o el clásico SERIAL PRIMARY KEY).

3.Elegir la clave primaria

Una buena clave primaria cumple tres cosas: es única, nunca está vacía y no cambia. Por eso suele usarse una clave sustituta (surrogate key): un número id sin significado propio, generado por la base de datos.

OpciónProblema o ventaja
El email como claveLa gente cambia de correo; habría que actualizar todo lo que lo use
El nombre como claveSe repite («Ana Torres» puede haber dos) y puede tener erratas
Un id numéricoNunca cambia, es corto y rápido de comparar

Esto no impide que el correo siga siendo único: se consigue con UNIQUE, como en la tabla clientes. Clave primaria (identifica) y valor único (evita repetidos) son dos ideas distintas.

4.Modificar y eliminar tablas

El diseño cambia con el tiempo. Estas instrucciones funcionan en SQLite y en PostgreSQL:

ALTER TABLE y DROP TABLE
-- Añadir una columna
ALTER TABLE clientes ADD COLUMN telefono TEXT;

-- Renombrar una tabla
ALTER TABLE clientes RENAME TO usuarios;

-- Eliminar la tabla y TODOS sus datos
DROP TABLE usuarios;

-- Variantes seguras: no fallan si ya existe / si no existe
CREATE TABLE IF NOT EXISTS clientes (id INTEGER PRIMARY KEY);
DROP TABLE IF EXISTS clientes;

⚠️ Importante · DROP TABLE no pregunta ni se deshace fácilmente

Elimina la tabla completa con todos sus datos. Hazlo solo si estás seguro y con copia de seguridad (lección 8). Además, al añadir una columna a una tabla con filas, esta se rellena con NULL (o con su DEFAULT): si pones NOT NULL necesitas un DEFAULT.

📌 Nota · SQLite modifica menos que PostgreSQL

SQLite solo permite cambios sencillos con ALTER TABLE (añadir, renombrar y, desde la versión 3.35, eliminar columnas). Cambiar el tipo de una columna o añadir restricciones a una existente suele exigir crear una tabla nueva y copiar los datos. PostgreSQL permite mucho más, por ejemplo ALTER TABLE t ALTER COLUMN c TYPE ….

5.Normalización básica: un dato, un lugar

Diseñar bien una tabla es decidir qué datos van en cada tabla. La normalización es un conjunto de reglas para evitar la repetición y los errores que causa. Veamos un diseño ingenuo: todo en una sola tabla de pedidos.

pedidoclienteemailproductostotal
1Ana Torresana@correo.comTeclado, Ratón165.50
2Ana Torresana@correo.comWebcam150.00
3Luis Pérezluis@correo.comMonitor 4K, Cable HDMI914.00

Problemas de esta tabla:

La solución es repartir los datos en tablas, cada una sobre una sola cosa, enlazadas con claves:

TablaColumnasGuarda
clientesid, nombre, emailCada cliente, una sola vez
productosid, nombre, categoria, precio, stockCada producto, una sola vez
pedidosid, cliente_id, fechaCada pedido y quién lo hizo
lineas_pedidopedido_id, producto_id, cantidadQué productos tiene cada pedido, y cuántos

💡 Consejo · Regla práctica

Si repites el mismo dato en muchas filas, o metes una lista en una celda, crea otra tabla. «Un dato, un lugar»: cada hecho se guarda una sola vez y se enlaza donde haga falta. En la próxima lección usaremos JOIN para volver a juntar estas tablas al consultar.

📌 Nota · No hace falta obsesionarse

Las formas normales llegan hasta la 5FN, pero en la práctica cumplir hasta la tercera da diseños limpios para casi cualquier aplicación. En ocasiones se duplica un dato a propósito para acelerar consultas (desnormalizar), pero se hace con criterio, no por desorden.

6.Buenos nombres y hábitos

7.Pruébalo: laboratorio de restricciones

Activa o desactiva restricciones en la tabla usuarios y mira cómo cambia la instrucción CREATE TABLE. Luego intenta insertar filas y observa cuándo la base de datos las rechaza. Hay ya un usuario guardado: Ana con id 1 y el correo ana@mail.com. (Es una simulación: usa los mismos mensajes de error que SQLite.)

🔒 Laboratorio de restricciones

    

idnombreemailedad

🧪 Ejemplo · Experimentos

1) Con todo activado, inserta con el correo ana@mail.com: UNIQUE lo rechaza. 2) Desactiva UNIQUE y repite: ahora entra y tendrás dos usuarios con el mismo correo. 3) Deja el nombre vacío con NOT NULL activo y sin él. 4) Pon edad 15 con y sin CHECK. 5) Escribe 1 en id con y sin PRIMARY KEY.

8.Errores frecuentes

📒 Apuntes para llevar

  • CREATE TABLE nombre (columna TIPO restricciones, …); define la estructura: columnas, tipos y reglas.
  • PRIMARY KEY identifica la fila; NOT NULL obliga a dar valor; UNIQUE impide repetidos; DEFAULT da un valor inicial; CHECK exige una condición.
  • Usa un id numérico como clave primaria y UNIQUE para datos que no deben repetirse (como el email).
  • ALTER TABLE modifica una tabla; DROP TABLE la elimina con todos sus datos.
  • Normalizar es repartir los datos en tablas: un dato, un lugar; sin listas en una celda ni datos repetidos.
  • La sintaxis de los identificadores automáticos difiere: INTEGER PRIMARY KEY en SQLite y GENERATED ALWAYS AS IDENTITY en PostgreSQL.
  • Nombres en minúsculas con guion bajo, tablas en plural y claves foráneas como cliente_id.

9.Glosario

TérminoSignificado
CREATE TABLEInstrucción que crea una tabla indicando sus columnas, tipos y restricciones.
PRIMARY KEYRestricción que identifica cada fila: valor único y nunca vacío.
NOT NULLRestricción que obliga a que la columna siempre tenga valor.
UNIQUERestricción que impide valores repetidos en una columna.
CHECKRestricción con una condición que cada valor debe cumplir.
Clave sustitutaIdentificador sin significado propio (un id numérico) que genera la base de datos.
NormalizaciónProceso de organizar las tablas para evitar datos repetidos y contradictorios.
Primera forma normal (1FN)Cada celda contiene un único valor, nunca una lista.

🧠 Comprueba lo aprendido

Elige una respuesta en cada pregunta. Verás al instante si acertaste y por qué.

¿Qué restricción impide que dos clientes tengan el mismo email?

¿Qué significa precio NUMERIC CHECK (precio > 0)?

¿Por qué es mala idea guardar 'Teclado, Ratón' en una sola celda?

¿Qué hace DROP TABLE clientes;?

¿Cuál es la mejor clave primaria para clientes?

Tu progreso se guarda en este navegador y se refleja en el índice del curso.

💡 🚀 ¡Ahora te toca!

La práctica fija lo aprendido. Pasa al ejercicio de esta lección.

Ir al ejercicio