ER Design Project: Library System
A library database that separates a title from a physical copy, models issue and return correctly, and shows why the obvious single book table quietly fails.
-
DBMS Fundamentals
- Data, Information and Databases
- What a DBMS Is and Why It Exists
- File System versus DBMS
- Advantages and Limitations of a DBMS
- Database Users and the Role of the DBA
- Three Level Architecture and Data Abstraction
- Logical and Physical Data Independence
- Schema, Instance and Metadata
- Database Applications and the Database System Environment
- Database Architecture
- Data Models
-
ER Model
- Entities, Entity Sets and Entity Types
- Types of Attributes in the ER Model
- Keys in the ER Model
- Relationships, Relationship Sets and Degree
- Cardinality and Participation Constraints
- Strong and Weak Entities
- Drawing and Reading ER Diagrams
- Extended ER: Generalisation, Specialisation and Aggregation
- Converting an ER Diagram into Relational Tables
- ER Design Projects
- Relational Model
- Relational Algebra
- Functional Dependencies
-
Normalisation
- Why Normalisation Exists: Anomalies and Redundancy
- First Normal Form
- Second Normal Form and Partial Dependency
- Third Normal Form and Transitive Dependency
- BCNF and BCNF Decomposition
- 4NF, 5NF, Multivalued and Join Dependencies
- Lossless Decomposition and Dependency Preservation
- Complete Worked Normalisation: Unnormalised to BCNF
- Denormalisation and When to Use It
Requirement
A library holds books. Each book has an ISBN, a title, a publisher and a year, and may have several authors. An author has an identifier and a name and may have written several books.
The library owns several physical copies of some books. Each copy has an accession number that is unique across the whole library, a shelf location and a condition.
Members have a membership number, a name, a category of either student or staff, and a contact number. Students may borrow four items, staff may borrow eight.
A copy is issued to a member on a date, and is due back on a date. When it is returned the return date is recorded, and a fine is calculated if it is late. The same copy is issued many times over its life, and the same member borrows many times.
Members may reserve a book, recording the date of reservation. A reservation is for a title, not for a particular copy.
The decision this project is really about
A book and a copy are different entities. The book is the title; the copy is the physical object on the shelf. Modelling them as one table is the classic library design mistake — you can then no longer say which of the six copies is on loan, and the ISBN stops identifying anything uniquely.
WRONG RIGHT
books books ( isbn, title, ... )
isbn one row per TITLE
title
is_issued copies ( accession_no, isbn, ... )
one row per PHYSICAL OBJECT
six copies of one title
cannot be represented issues ( accession_no, ... )
a loan is of a COPYStep 1 — Entities
| Entity | Attributes | Key | Type |
|---|---|---|---|
| BOOK | isbn, title, publisher, year | isbn | Strong |
| AUTHOR | author_id, author_name | author_id | Strong |
| COPY | accession_no, shelf, condition | accession_no | Strong |
| MEMBER | member_no, name, category, contact | member_no | Strong |
| ISSUE | issue_id, issued_on, due_on, returned_on, fine | issue_id | Strong |
| RESERVATION | reserved_on, status | member_no + isbn + reserved_on | Strong |
COPY is strong, not weak, because the accession number is unique across the whole library. Had accession numbers restarted per title, COPY would have been weak with a partial key.
Step 2 — Relationships
| Relationship | Between | Ratio | Participation | Attributes |
|---|---|---|---|---|
| WRITTEN_BY | BOOK — AUTHOR | M:N | Book total | author_order |
| COPY_OF | COPY — BOOK | N:1 | Copy total | — |
| ISSUED_COPY | ISSUE — COPY | N:1 | Issue total | — |
| ISSUED_TO | ISSUE — MEMBER | N:1 | Issue total | — |
| RESERVES | MEMBER — BOOK | M:N | Both partial | reserved_on, status |
Step 3 — The ER diagram
+----------+ M N +----------+
| BOOK |----< WRITTEN_BY >-----| AUTHOR |
+----+-----+ (author_order) +----------+
1 | | M
| +--------< RESERVES >-------+
| (reserved_on, status) | N
| +-----v-----+
< COPY_OF > | MEMBER |
| N +-----+-----+
+--v-------+ | 1
| COPY | |
+----+-----+ < ISSUED_TO >
1 | | N
+--------< ISSUED_COPY >-------+
| N
+------v-------+
| ISSUE |
+--------------+
issue_id, issued_on, due_on,
returned_on (nullable), fineStep 4 — The relational schema
books ( isbn PK, title NOT NULL, publisher, pub_year )
authors ( author_id PK, author_name NOT NULL )
book_authors ( isbn -> books, author_id -> authors
, author_order NOT NULL
, PK ( isbn, author_id ) )
copies ( accession_no PK
, isbn NOT NULL -> books
, shelf, copy_condition )
members ( member_no PK, member_name NOT NULL
, category NOT NULL -- student or staff
, contact )
issues ( issue_id PK
, accession_no NOT NULL -> copies
, member_no NOT NULL -> members
, issued_on NOT NULL
, due_on NOT NULL
, returned_on NULL -- null means ON LOAN
, fine DEFAULT 0 )
reservations ( member_no -> members
, isbn -> books
, reserved_on
, status NOT NULL -- waiting, met, cancelled
, PK ( member_no, isbn, reserved_on ) )
7 tables.Step 5 — Where the rules actually live
| Rule | Enforced by |
|---|---|
| An accession number identifies one physical copy | Primary key on copies |
| A copy belongs to exactly one title | isbn NOT NULL foreign key |
| A copy is on loan when its latest issue has no return date | Derived — returned_on IS NULL. Do not add an is_issued flag; two sources of truth will disagree. |
| A copy cannot be issued twice at once | Not expressible as a simple key. Needs a partial uniqueness rule or a check at issue time. |
| Students borrow four, staff eight | Application or trigger. A count limit is not a column constraint. |
| Fine is calculated from due date and return date | Derived at return time, then stored because the rate may change later. |
The is_issued flag is the trap. It looks convenient and it duplicates a fact that the issue table already holds. The moment a return is recorded and the flag is not cleared, the catalogue lies. Derive it.Verification questions
- Which copies of a title are currently on loan, and to whom?
- How many copies of a title does the library own, and how many are available now?
- Which members have overdue items today, and what is the fine so far?
- Which titles have a waiting reservation but no available copy?
- How many times has one copy been issued in its life?
Common mistakes
- Merging book and copy into one table, making multiple copies unrepresentable.
- Adding an
is_issuedflag beside the issue history. - Issuing a title rather than a copy, so the system cannot say which physical object is out.
- Making
returned_onnot null and creating a separate returns table, which complicates every query. - Reserving a copy rather than a title, when the member does not care which copy they get.
Practice
- Add a rule that a reservation expires after seven days, and say where it is enforced.
- Write the condition that identifies every copy currently on loan.
- Add fine payments, where a member may pay a fine in parts, and state whether the payment entity is weak.
Conclusion
Seven tables, and one modelling decision that carries the whole design: separate the title from the physical copy. The second lesson is to derive availability from the loan history rather than storing a flag that can drift.