Esempi / Gestione di una biblioteca
Gestione di una biblioteca
Lo schema di una biblioteca si regge su una distinzione. Il libro è un titolo in catalogo, la copia è il volume fisico sullo scaffale. Gli iscritti prendono in prestito le copie, non i libri, mentre le prenotazioni si fanno sul libro. Gli autori si collegano con una tabella ponte, perché un libro può avere più autori.
Qui sotto ErdDocs disegna questo schema dal suo SQL, con tutte le tabelle e le relazioni. Nella scheda «Dizionario dati» c’è la versione da stampare, completa e gratis in questa pagina. Il SQL è più in basso.
Passa sopra una tabella per evidenziarne le relazioni. Un clic le fissa.
A cosa serve ogni tabella
- books / copiesLa voce di catalogo e la copia con il codice a barre. La maggior parte degli esercizi sulla biblioteca si riduce a questa distinzione.
- authors / book_authorsRelazione molti a molti. Con un libro a due autori, un author_id diretto non regge più.
- membersGli iscritti si riconoscono dal numero di tessera, card_no.
- loansIl prestito è legato alla copia, perché serve sapere quale volume è fuori e in ritardo.
- reservationsLa prenotazione è legata al libro. L’iscritto vuole il titolo, qualunque copia torni per prima.
Scelte di progetto da riprendere
- I prestiti puntano alle copie, le prenotazioni ai libri. Mescolare i due livelli è l’errore classico. Lo schema non sa più rispondere né a «chi ha proprio questo volume» né a «chi avvisare per primo».
- returned_on ammette NULL. Così sostituisce un campo «restituito» e conserva la data nella stessa colonna.
- L’ISBN è univoco ma ammette NULL. Esistono volumi vecchi e materiali interni senza ISBN, e con un NOT NULL i dati reali violerebbero il vincolo.
Il SQL
Dialetto PostgreSQL. Questo SQL è già nello strumento qui sopra, e puoi copiarlo liberamente nel tuo database o in una migrazione.
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 per i volumi anteriori all’ISBN o i materiali interni';
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 'Il volume fisico; un libro richiesto ha molte copie';
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 finché la copia è in prestito';
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 'Prenotazione sul LIBRO: qualsiasi copia restituita la soddisfa';Domande frequenti
Dove vanno le multe per ritardo?
In una tabella fines che fa riferimento a loans, perché la multa nasce da un prestito in ritardo. Contiene importo, data e data di pagamento. Per un esercizio va bene anche calcolarle al volo dalla scadenza. L’importante è motivare la scelta.
Cosa cambia con gli e-book?
Gli e-book non hanno copie, quindi il prestito diventa una questione di licenze. Puoi aggiungere una tabella licenses accanto a copies, con il numero di prestiti contemporanei. Oppure puoi legare i prestiti direttamente al libro e controllare il numero di prestiti nell’applicazione.