Cómo se trabaja
Estos veinte ejercicios son de diseño: hay que leer el planteo y escribir el CREATE TABLE —o los CREATE TABLE— que lo resuelvan. No hay una única solución posible y está bien que así sea: dos personas pueden llegar a dos modelos distintos y los dos funcionar.
Lo que sí hay que cumplir son los requisitos que enumera cada planteo: si dice que un dato es obligatorio, va NOT NULL; si dice que no se puede repetir, va UNIQUE; si dice que un registro pertenece a otro, va una clave foránea. Y hay que decidir en cada tabla cuál es su clave primaria.
Lo más útil es probar: se escribe el SQL en phpMyAdmin o en el gestor que estén usando, se ejecuta y se revisa con DESCRIBE que las restricciones hayan quedado donde debían. Si algo no se puede ejecutar, algo está mal.
Cada ejercicio tiene su solución escondida, para comparar después de intentarlo. Están ordenados por dificultad: los primeros son de una sola tabla y los últimos combinan varias relaciones.
Primeros pasos: una sola tabla
En estos cuatro ejercicios alcanza con una tabla. Igual hay que pensar dos cosas: cuál es la clave primaria y qué campo es obligatorio y único, porque siempre hay uno que no se puede repetir.
Ejercicio 1 · La fotocopiadora del barrio
Una fotocopiadora quiere tener su lista de precios. De cada trabajo se guarda el nombre (por ejemplo «Anillado», «Copia color»), cuánto sale por hoja y si es en color o no. El nombre del trabajo no se puede repetir y el precio por hoja es obligatorio. Las copias en blanco y negro son las más comunes, así que el sistema tiene que asumir que un trabajo es en blanco y negro salvo que se aclare lo contrario.
CREATE DATABASE fotocopiadora;
USE fotocopiadora;
CREATE TABLE trabajos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(60) NOT NULL UNIQUE,
precio_hoja DECIMAL(10, 2) NOT NULL,
color TINYINT(1) NOT NULL DEFAULT 0
);
Ejercicio 2 · Agenda de contactos
Una agenda personal: el nombre de la persona (obligatorio), el teléfono, el correo y la localidad. Los teléfonos pueden faltar, pero el correo, cuando se carga, no se puede repetir en otra persona. El nombre sí se puede repetir: hay más de una persona con el mismo nombre.
CREATE DATABASE agenda;
USE agenda;
CREATE TABLE contactos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(80) NOT NULL,
telefono VARCHAR(20),
correo VARCHAR(120) UNIQUE,
localidad VARCHAR(60)
);
Ejercicio 3 · El inventario de la ferretería
La ferretería guarda sus productos: nombre, un código interno que la casa usa para identificarlos, el precio y cuántas unidades hay en el depósito. El código es obligatorio y no se repite. El stock arranca en cero cuando se carga un producto nuevo, y el precio es obligatorio: no hay producto sin precio.
CREATE DATABASE ferreteria;
USE ferreteria;
CREATE TABLE productos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(80) NOT NULL,
codigo VARCHAR(20) NOT NULL UNIQUE,
precio DECIMAL(10, 2) NOT NULL,
stock INT NOT NULL DEFAULT 0
);
Ejercicio 4 · El catálogo de la disquería
Un catálogo de discos: título, artista, año de edición y sello. El título no se repite, y el año y el sello son obligatorios. Ojo con una tentación: no hace falta guardar el país del artista, porque el artista puede tener discos con sellos de distintos países y no queremos repetir el dato en cada disco.
CREATE DATABASE disqueria;
USE disqueria;
CREATE TABLE discos (
id INT AUTO_INCREMENT PRIMARY KEY,
titulo VARCHAR(120) NOT NULL UNIQUE,
artista VARCHAR(80) NOT NULL,
anio INT NOT NULL,
sello VARCHAR(60) NOT NULL
);
Un paso más: dos tablas relacionadas
Acá aparece la primera clave foránea. La pregunta que hay que hacerse siempre es la misma: ¿cuál de las dos tablas es «la del muchos»? La clave foránea va en esa, porque es la que guarda la referencia.
Ejercicio 5 · La veterinaria
Una veterinaria registra a sus clientes y a sus mascotas. De cada cliente se guarda el nombre, el documento (obligatorio y único) y el teléfono. De cada mascota, el nombre, la especie y su fecha de nacimiento, que puede no conocerse. Una mascota pertenece a un solo cliente, y un cliente puede tener varias mascotas.
CREATE DATABASE veterinaria_ej;
USE veterinaria_ej;
CREATE TABLE clientes (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(80) NOT NULL,
documento VARCHAR(15) NOT NULL UNIQUE,
telefono VARCHAR(20)
);
CREATE TABLE mascotas (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(40) NOT NULL,
especie VARCHAR(30) NOT NULL,
nacimiento DATE,
cliente_id INT NOT NULL,
FOREIGN KEY (cliente_id) REFERENCES clientes(id)
);
Ejercicio 6 · Las divisiones del colegio
El colegio necesita saber qué alumnos hay en cada división. De cada división se guarda el nombre («1º A») y el año; el nombre de la división no puede repetirse. De cada alumno, el nombre, el documento (obligatorio y único) y la fecha de nacimiento. Un alumno pertenece a una sola división.
CREATE DATABASE colegio;
USE colegio;
CREATE TABLE divisiones (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(40) NOT NULL UNIQUE,
anio INT NOT NULL
);
CREATE TABLE alumnos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(80) NOT NULL,
documento VARCHAR(15) NOT NULL UNIQUE,
nacimiento DATE NOT NULL,
division_id INT NOT NULL,
FOREIGN KEY (division_id) REFERENCES divisiones(id)
);
Ejercicio 7 · Los equipos del torneo
Un torneo barrial: de cada equipo se guarda el nombre (único), el barrio y el año de fundación. De cada jugador, el nombre, el documento (único), la fecha de nacimiento y el número de camiseta. Un jugador pertenece a un solo equipo, y el número de camiseta no se repite dentro del mismo equipo —dos jugadores de equipos distintos sí pueden tener el mismo número—.
CREATE DATABASE torneo;
USE torneo;
CREATE TABLE equipos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(60) NOT NULL UNIQUE,
barrio VARCHAR(60),
fundacion INT
);
CREATE TABLE jugadores (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(80) NOT NULL,
documento VARCHAR(15) NOT NULL UNIQUE,
nacimiento DATE NOT NULL,
camiseta INT NOT NULL,
equipo_id INT NOT NULL,
FOREIGN KEY (equipo_id) REFERENCES equipos(id)
);
Ejercicio 8 · Los recitales del año
Una productora organiza recitales. De cada banda se guarda el nombre (único) y el género. De cada recital, la fecha, el estadio y cuántas entradas se vendieron; el estadio y la fecha son obligatorios. Una banda puede dar varios recitales, y cada recital es de una sola banda.
CREATE DATABASE recitales;
USE recitales;
CREATE TABLE bandas (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(80) NOT NULL UNIQUE,
genero VARCHAR(40)
);
CREATE TABLE recitales (
id INT AUTO_INCREMENT PRIMARY KEY,
fecha DATE NOT NULL,
estadio VARCHAR(80) NOT NULL,
entradas INT NOT NULL DEFAULT 0,
banda_id INT NOT NULL,
FOREIGN KEY (banda_id) REFERENCES bandas(id)
);
Ejercicio 9 · Las ventas de la panadería
La panadería quiere seguir sus ventas del día. De cada producto se guarda el nombre (único) y el precio. De cada venta, la fecha, la cantidad y el producto vendido. El precio no se guarda en la venta: queda en la tabla de productos, porque el día que cambie hay que cambiarlo en un solo lugar.
CREATE DATABASE panaderia;
USE panaderia;
CREATE TABLE productos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(60) NOT NULL UNIQUE,
precio DECIMAL(10, 2) NOT NULL
);
CREATE TABLE ventas (
id INT AUTO_INCREMENT PRIMARY KEY,
fecha DATE NOT NULL,
cantidad INT NOT NULL,
producto_id INT NOT NULL,
FOREIGN KEY (producto_id) REFERENCES productos(id)
);
Tres tablas o más
Los que siguen tienen dos o tres relaciones. Cuando aparecen dos tablas que se relacionan entre sí muchas veces —alumnos y materias, jugadores y partidos—, la solución es una tabla intermedia con dos claves foráneas. Es la misma idea que la tabla de préstamos de la biblioteca.
Ejercicio 10 · La biblioteca
El caso que se usó en toda la unidad: socios, libros y préstamos. Del socio, el nombre, el documento (único) y la fecha de alta. Del libro, el título y el autor. Del préstamo, la fecha de salida y la de devolución, que queda vacía mientras el libro no vuelva. Un préstamo siempre tiene un socio y un libro, y los dos tienen que existir.
CREATE DATABASE biblioteca_ej;
USE biblioteca_ej;
CREATE TABLE socios (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(80) NOT NULL,
documento VARCHAR(15) NOT NULL UNIQUE,
alta DATE NOT NULL
);
CREATE TABLE libros (
id INT AUTO_INCREMENT PRIMARY KEY,
titulo VARCHAR(120) NOT NULL,
autor VARCHAR(80) NOT NULL
);
CREATE TABLE prestamos (
id INT AUTO_INCREMENT PRIMARY KEY,
socio_id INT NOT NULL,
libro_id INT NOT NULL,
salida DATE NOT NULL,
vuelta DATE,
FOREIGN KEY (socio_id) REFERENCES socios(id),
FOREIGN KEY (libro_id) REFERENCES libros(id)
);
Ejercicio 11 · Las funciones del cine
Un cine: películas, salas y funciones. De la película, el título (único), la duración en minutos y la clasificación. De la sala, el nombre (único) y cuántas butacas tiene. De la función, la fecha, la hora y el precio de la entrada. Una función pasa una película en una sala, y la misma película puede estar en varias salas y en varios horarios.
CREATE DATABASE cine;
USE cine;
CREATE TABLE peliculas (
id INT AUTO_INCREMENT PRIMARY KEY,
titulo VARCHAR(120) NOT NULL UNIQUE,
duracion_min INT NOT NULL,
clasificacion VARCHAR(10)
);
CREATE TABLE salas (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(40) NOT NULL UNIQUE,
butacas INT NOT NULL
);
CREATE TABLE funciones (
id INT AUTO_INCREMENT PRIMARY KEY,
fecha DATE NOT NULL,
hora TIME NOT NULL,
precio DECIMAL(10, 2) NOT NULL,
pelicula_id INT NOT NULL,
sala_id INT NOT NULL,
FOREIGN KEY (pelicula_id) REFERENCES peliculas(id),
FOREIGN KEY (sala_id) REFERENCES salas(id)
);
Ejercicio 12 · El taller mecánico
El taller registra clientes, sus vehículos y las reparaciones. Del cliente, el nombre, el documento (único) y el teléfono. Del vehículo, la patente (obligatoria y única), la marca, el modelo y el año. Un cliente puede tener más de un vehículo. De cada reparación se guarda la fecha, qué se hizo y cuánto costó, y siempre corresponde a un vehículo.
CREATE DATABASE taller;
USE taller;
CREATE TABLE clientes (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(80) NOT NULL,
documento VARCHAR(15) NOT NULL UNIQUE,
telefono VARCHAR(20)
);
CREATE TABLE vehiculos (
id INT AUTO_INCREMENT PRIMARY KEY,
patente VARCHAR(10) NOT NULL UNIQUE,
marca VARCHAR(40) NOT NULL,
modelo VARCHAR(40) NOT NULL,
anio INT NOT NULL,
cliente_id INT NOT NULL,
FOREIGN KEY (cliente_id) REFERENCES clientes(id)
);
CREATE TABLE reparaciones (
id INT AUTO_INCREMENT PRIMARY KEY,
fecha DATE NOT NULL,
detalle VARCHAR(200) NOT NULL,
costo DECIMAL(10, 2) NOT NULL,
vehiculo_id INT NOT NULL,
FOREIGN KEY (vehiculo_id) REFERENCES vehiculos(id)
);
Ejercicio 13 · Las reservas del hotel
El hotel tiene habitaciones y huéspedes. De la habitación, el número (único), el piso y cuántas camas. Del huésped, el nombre, el documento (único) y el teléfono. De la reserva, la fecha de entrada, la de salida y el importe total. Una reserva es de un huésped en una habitación, y un huésped puede tener varias reservas a lo largo del tiempo.
CREATE DATABASE hotel;
USE hotel;
CREATE TABLE habitaciones (
id INT AUTO_INCREMENT PRIMARY KEY,
numero INT NOT NULL UNIQUE,
piso INT NOT NULL,
camas INT NOT NULL
);
CREATE TABLE huespedes (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(80) NOT NULL,
documento VARCHAR(15) NOT NULL UNIQUE,
telefono VARCHAR(20)
);
CREATE TABLE reservas (
id INT AUTO_INCREMENT PRIMARY KEY,
entrada DATE NOT NULL,
salida DATE NOT NULL,
importe DECIMAL(10, 2) NOT NULL,
huesped_id INT NOT NULL,
habitacion_id INT NOT NULL,
FOREIGN KEY (huesped_id) REFERENCES huespedes(id),
FOREIGN KEY (habitacion_id) REFERENCES habitaciones(id)
);
Ejercicio 14 · Los turnos del consultorio
Un consultorio con dos médicos. De cada médico se guarda el nombre, la matrícula (única) y la especialidad. De cada paciente, el nombre, el documento (único) y el teléfono. De cada turno, la fecha, la hora y el consultorio. Un turno es de un paciente con un médico, y no puede haber dos turnos del mismo médico a la misma hora.
CREATE DATABASE consultorio;
USE consultorio;
CREATE TABLE medicos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(80) NOT NULL,
matricula VARCHAR(20) NOT NULL UNIQUE,
especialidad VARCHAR(60) NOT NULL
);
CREATE TABLE pacientes (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(80) NOT NULL,
documento VARCHAR(15) NOT NULL UNIQUE,
telefono VARCHAR(20)
);
CREATE TABLE turnos (
id INT AUTO_INCREMENT PRIMARY KEY,
fecha DATE NOT NULL,
hora TIME NOT NULL,
medico_id INT NOT NULL,
paciente_id INT NOT NULL,
FOREIGN KEY (medico_id) REFERENCES medicos(id),
FOREIGN KEY (paciente_id) REFERENCES pacientes(id)
);
Ejercicio 15 · Los alquileres del videoclub
Un videoclub. De cada película: título (único), género y año. De cada socio: nombre, documento (único) y fecha de alta. De cada alquiler: la fecha de retiro y la de devolución, que queda vacía mientras no la traigan. Un socio puede alquilar muchas películas y la misma película puede alquilarse muchas veces.
CREATE DATABASE videoclub_ej;
USE videoclub_ej;
CREATE TABLE peliculas (
id INT AUTO_INCREMENT PRIMARY KEY,
titulo VARCHAR(120) NOT NULL UNIQUE,
genero VARCHAR(40) NOT NULL,
anio INT NOT NULL
);
CREATE TABLE socios (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(80) NOT NULL,
documento VARCHAR(15) NOT NULL UNIQUE,
alta DATE NOT NULL
);
CREATE TABLE alquileres (
id INT AUTO_INCREMENT PRIMARY KEY,
socio_id INT NOT NULL,
pelicula_id INT NOT NULL,
retirada DATE NOT NULL,
devuelta DATE,
FOREIGN KEY (socio_id) REFERENCES socios(id),
FOREIGN KEY (pelicula_id) REFERENCES peliculas(id)
);
Ejercicio 16 · Las inscripciones al gimnasio
El gimnasio dicta actividades y los socios se inscriben en las que quieran. De la actividad: nombre (único), día de la semana, horario y cupo máximo. Del socio: nombre, documento (único) y teléfono. De la inscripción: la fecha en que se anotó. Un socio no puede anotarse dos veces en la misma actividad, pero sí en varias distintas, y una actividad tiene muchos inscriptos: esa es una relación de muchos a muchos, y necesita su tabla intermedia.
CREATE DATABASE gimnasio_ej;
USE gimnasio_ej;
CREATE TABLE actividades (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(60) NOT NULL UNIQUE,
dia VARCHAR(15) NOT NULL,
horario TIME NOT NULL,
cupo INT NOT NULL
);
CREATE TABLE socios (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(80) NOT NULL,
documento VARCHAR(15) NOT NULL UNIQUE,
telefono VARCHAR(20)
);
CREATE TABLE inscripciones (
id INT AUTO_INCREMENT PRIMARY KEY,
fecha DATE NOT NULL,
socio_id INT NOT NULL,
actividad_id INT NOT NULL,
FOREIGN KEY (socio_id) REFERENCES socios(id),
FOREIGN KEY (actividad_id) REFERENCES actividades(id)
);
Ejercicio 17 · Las notas de la escuela
La escuela necesita registrar las notas. De cada curso: nombre (único) y año. De cada alumno: nombre, documento (único) y curso. De cada materia: nombre y curso al que pertenece. Y de cada nota: el valor (permite decimales), la fecha y de quién es. Un alumno tiene notas en varias materias y una materia tiene notas de varios alumnos: hace falta una tabla con dos claves foráneas.
CREATE DATABASE escuela_ej;
USE escuela_ej;
CREATE TABLE cursos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(40) NOT NULL UNIQUE,
anio INT NOT NULL
);
CREATE TABLE alumnos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(80) NOT NULL,
documento VARCHAR(15) NOT NULL UNIQUE,
curso_id INT NOT NULL,
FOREIGN KEY (curso_id) REFERENCES cursos(id)
);
CREATE TABLE materias (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(60) NOT NULL,
curso_id INT NOT NULL,
FOREIGN KEY (curso_id) REFERENCES cursos(id)
);
CREATE TABLE notas (
id INT AUTO_INCREMENT PRIMARY KEY,
nota DECIMAL(4, 2) NOT NULL,
fecha DATE NOT NULL,
alumno_id INT NOT NULL,
materia_id INT NOT NULL,
FOREIGN KEY (alumno_id) REFERENCES alumnos(id),
FOREIGN KEY (materia_id) REFERENCES materias(id)
);
Ejercicio 18 · Los pedidos del comercio
Un comercio que vende por internet. De cada cliente: nombre, documento (único) y correo. De cada producto: nombre (único), precio y stock. De cada pedido: la fecha y el estado («pendiente», «enviado», «entregado»). Y un pedido puede tener varios productos, cada uno con su cantidad, así que hace falta una cuarta tabla para el detalle: el precio no se guarda ahí, porque ya está en productos.
CREATE DATABASE comercio;
USE comercio;
CREATE TABLE clientes (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(80) NOT NULL,
documento VARCHAR(15) NOT NULL UNIQUE,
correo VARCHAR(120)
);
CREATE TABLE productos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(80) NOT NULL UNIQUE,
precio DECIMAL(10, 2) NOT NULL,
stock INT NOT NULL DEFAULT 0
);
CREATE TABLE pedidos (
id INT AUTO_INCREMENT PRIMARY KEY,
fecha DATE NOT NULL,
estado VARCHAR(20) NOT NULL DEFAULT 'pendiente',
cliente_id INT NOT NULL,
FOREIGN KEY (cliente_id) REFERENCES clientes(id)
);
CREATE TABLE detalle_pedidos (
id INT AUTO_INCREMENT PRIMARY KEY,
cantidad INT NOT NULL,
pedido_id INT NOT NULL,
producto_id INT NOT NULL,
FOREIGN KEY (pedido_id) REFERENCES pedidos(id),
FOREIGN KEY (producto_id) REFERENCES productos(id)
);
Ejercicio 19 · Las ventas de la farmacia
La farmacia vende medicamentos y quiere saber quién compró qué. De cada medicamento: nombre, presentación («caja», «frasco») y precio. De cada cliente: nombre, documento (único) y obra social, que puede no tener. De cada venta: la fecha, la cantidad y el descuento aplicado. Un cliente puede comprar muchas veces y un medicamento se vende muchas veces.
CREATE DATABASE farmacia;
USE farmacia;
CREATE TABLE medicamentos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(80) NOT NULL,
presentacion VARCHAR(30) NOT NULL,
precio DECIMAL(10, 2) NOT NULL
);
CREATE TABLE clientes (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(80) NOT NULL,
documento VARCHAR(15) NOT NULL UNIQUE,
obra_social VARCHAR(60)
);
CREATE TABLE ventas (
id INT AUTO_INCREMENT PRIMARY KEY,
fecha DATE NOT NULL,
cantidad INT NOT NULL,
descuento DECIMAL(5, 2) NOT NULL DEFAULT 0,
cliente_id INT NOT NULL,
medicamento_id INT NOT NULL,
FOREIGN KEY (cliente_id) REFERENCES clientes(id),
FOREIGN KEY (medicamento_id) REFERENCES medicamentos(id)
);
Ejercicio 20 · El museo
Un museo con obras, salas y visitas guiadas. De cada sala: nombre (único), piso y capacidad. De cada obra: título, autor y año de creación; una obra está en una sola sala, y una sala tiene muchas obras. De cada visita guiada: la fecha, el horario y el guía a cargo. Y hay un dato más: una misma obra puede incluirse en varias visitas, y una visita recorre varias obras, así que hace falta una tabla intermedia entre obras y visitas.
CREATE DATABASE museo;
USE museo;
CREATE TABLE salas (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(60) NOT NULL UNIQUE,
piso INT NOT NULL,
capacidad INT NOT NULL
);
CREATE TABLE obras (
id INT AUTO_INCREMENT PRIMARY KEY,
titulo VARCHAR(120) NOT NULL,
autor VARCHAR(80) NOT NULL,
anio INT,
sala_id INT NOT NULL,
FOREIGN KEY (sala_id) REFERENCES salas(id)
);
CREATE TABLE visitas (
id INT AUTO_INCREMENT PRIMARY KEY,
fecha DATE NOT NULL,
horario TIME NOT NULL,
guia VARCHAR(80) NOT NULL,
sala_id INT NOT NULL,
FOREIGN KEY (sala_id) REFERENCES salas(id)
);
CREATE TABLE visitas_obras (
id INT AUTO_INCREMENT PRIMARY KEY,
visita_id INT NOT NULL,
obra_id INT NOT NULL,
FOREIGN KEY (visita_id) REFERENCES visitas(id),
FOREIGN KEY (obra_id) REFERENCES obras(id)
);