Ir al contenido principal

Ejercicios

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)
);