Ejemplos / Sistema de biblioteca
Sistema de biblioteca
El esquema de una biblioteca se apoya en una sola separación. El libro es un título del catálogo, y el ejemplar, el objeto físico en el estante. Los socios se llevan ejemplares, no libros, pero las reservas se hacen sobre el libro. Los autores se unen con una tabla intermedia, porque hay libros con varios autores.
Abajo, ErdDocs dibuja este esquema a partir de su SQL, con todas las tablas y relaciones. En la pestaña «Diccionario de datos» tienes la versión imprimible, completa y gratis en esta página. El SQL está más abajo.
Pasa el cursor sobre una tabla para resaltar sus relaciones y haz clic para fijarlas.
Qué hace cada tabla
- books / copiesLa ficha del catálogo frente al ejemplar con código de barras. La mayoría de los ejercicios de biblioteca se reducen a esta separación.
- authors / book_authorsMuchos a muchos. Un libro con dos autores rompe enseguida un author_id directo.
- membersLas personas usan el número de carnet, card_no.
- loansEl préstamo se une al ejemplar, porque hay que saber qué objeto físico está fuera y vencido.
- reservationsLa reserva se une al libro. El socio quiere el título, sea cual sea el ejemplar que vuelva primero.
Decisiones de diseño que vale la pena copiar
- Los préstamos apuntan a ejemplares y las reservas a libros. Mezclar los dos niveles es el error clásico. Así el esquema no puede responder «quién tiene este ejemplar» ni «a quién avisar después».
- returned_on admite nulos. Hace el trabajo de un indicador «devuelto» y además guarda la fecha en la misma columna.
- El ISBN es único pero admite nulos. Existe material antiguo e interno sin ISBN, y con NOT NULL esos datos reales violarían la restricción.
El SQL
Dialecto PostgreSQL. Este SQL ya está en la herramienta de arriba, y puedes copiarlo libremente a tu base de datos o a una migración.
CREATE TABLE authors (
id bigserial PRIMARY KEY,
full_name varchar(120) NOT NULL
);
CREATE TABLE books (
id bigserial PRIMARY KEY,
isbn varchar(17) UNIQUE,
title varchar(240) NOT NULL,
published smallint
);
COMMENT ON COLUMN books.isbn IS 'NULL para material anterior al ISBN o interno';
CREATE TABLE book_authors (
book_id bigint NOT NULL REFERENCES books(id),
author_id bigint NOT NULL REFERENCES authors(id),
PRIMARY KEY (book_id, author_id)
);
CREATE TABLE copies (
id bigserial PRIMARY KEY,
book_id bigint NOT NULL REFERENCES books(id),
barcode varchar(20) NOT NULL UNIQUE,
shelf varchar(20),
condition varchar(20) NOT NULL DEFAULT 'good'
);
COMMENT ON TABLE copies IS 'El objeto físico; un libro popular tiene muchos ejemplares';
CREATE TABLE members (
id bigserial PRIMARY KEY,
card_no varchar(20) NOT NULL UNIQUE,
full_name varchar(120) NOT NULL,
joined_on date NOT NULL
);
CREATE TABLE loans (
id bigserial PRIMARY KEY,
copy_id bigint NOT NULL REFERENCES copies(id),
member_id bigint NOT NULL REFERENCES members(id),
loaned_on date NOT NULL,
due_on date NOT NULL,
returned_on date
);
COMMENT ON COLUMN loans.returned_on IS 'NULL mientras el ejemplar está prestado';
CREATE TABLE reservations (
id bigserial PRIMARY KEY,
book_id bigint NOT NULL REFERENCES books(id),
member_id bigint NOT NULL REFERENCES members(id),
placed_at timestamptz NOT NULL DEFAULT now(),
fulfilled boolean NOT NULL DEFAULT false
);
COMMENT ON TABLE reservations IS 'La reserva es sobre el LIBRO: cualquier ejemplar devuelto la cumple';Preguntas frecuentes
¿Dónde van las multas?
En una tabla fines que referencia a loans, porque la multa se cobra por un préstamo vencido. Guarda el importe, la fecha y la fecha de pago. Para un trabajo de clase también sirve calcularlas al vuelo a partir de la fecha de devolución. Lo importante es explicar cuál elegiste y por qué.
¿Cómo cambia el esquema con libros electrónicos?
Un libro electrónico no tiene ejemplares, así que el préstamo pasa a ser una cuestión de licencias. Puedes crear una tabla licenses paralela a copies, con el número de préstamos simultáneos. O puedes prestar directamente el libro y controlar la concurrencia en la aplicación.