ER diagram: from a description to a schema
In short: An ER (entity-relationship) diagram shows the entities, their attributes and the relationships between them with their cardinality, before they become tables with CREATE TABLE.
Problem
The library notebook
A neighbourhood library keeps its loans in a notebook. The librarian describes what she wants from the new program:
“We have about 2,000 books, some of them in several copies. Members sign up with a name and an email. Anyone can borrow a book for three weeks. I want to know which books are out, who has them and who is late. And I want to search by author.”
Before the first CREATE TABLE, you need to know what tables there are, what they keep and how they connect. Otherwise, a month later, you will be redoing the schema with a full database.
The idea
Entities and attributes
You go through the description and look for the entities: the things you keep data about. They are usually nouns.
- Member: name, email, when they signed up.
- Book: title, year.
- Author: name.
- Copy: one physical copy of the book, on a certain shelf. “Some of them in several copies” means that the book and the copy are different things.
- Loan: which copy, which member, when it was taken, when it is due, when it was returned.
Each entity becomes a table, and its attributes become columns. A loan is a verb, but it has its own attributes (dates), so it is a table too.
“Which are out” and “who is late” are not columns. They are questions that queries will answer.
The idea
Relationships and cardinality
Next you say how the entities connect and how many to how many. The picture of this is called an ER diagram (entity-relationship). Its most common notation is crow's foot, named after the sign for “many”, which looks like a bird's foot.
Each end of a line has two signs. The sign next to the table says how many at most, and the other one how many at least. This is how they are written at the right end:
||exactly one;o|zero or one;|{one or many;o{zero or many.{is the “foot”.
At the left end they are mirrored: ||, |o, }|, }o.
Here is the library. The notation is Mermaid, which GitHub and many editors draw as a picture:
erDiagrammembers ||--o{ loans : "borrows"copies ||--o{ loans : "is lent"books ||--|{ copies : "has"books ||--|{ book_authors : "is by"authors ||--o{ book_authors : "writes"The text after the colon is the label on the line. Mermaid requires it, and it means nothing for the schema.
members ||--o{ loans reads like this: one member has zero or many loans, and each loan belongs to exactly one member. books ||--|{ copies: every book has at least one copy, and each copy is of exactly one book.
Try it
What is the relationship?
The idea
From the diagram to tables
The rules are from the previous lesson:
- 1:N: a foreign key on the “many” side (
copies.book_id,loans.copy_id,loans.member_id). - M:N: a link table with a primary key of both columns (
book_authors). - 1:1: a foreign key with
UNIQUE. The library has none.
members
- PK
idinteger nametext *emailtext *joined_attext *
authors
- PK
idinteger nametext *
books
- PK
idinteger titletext *yearinteger
book_authors
- PK
book_idinteger→ books - PK
author_idinteger→ authors
copies
- PK
idinteger - FK
book_idinteger *→ books shelftext *
loans
- PK
idinteger - FK
copy_idinteger *→ copies - FK
member_idinteger *→ members loaned_attext *due_attext *returned_attext
The fields below have this schema and a few books and members. Which copies of “Under the Yoke” are there, and on which shelf?
More precisely, if you are curious
returned_at is NULL while the book is out. So one column keeps both “has it been returned” and “when”. Another option is a status column, but then you have to make sure the two never contradict each other.
Diagrams are also drawn with tools such as dbdiagram.io and draw.io, and most database programs (DBeaver, DataGrip, pgAdmin) draw an ER diagram from an existing database. The notation is the same.
See it
Book or copy?
The temptation is to point the loan straight at the book. Run the history of “Under the Yoke”:
Copy 1 was with two members one after the other, and copy 2 is with Borislav now. If the loan kept only “Under the Yoke”, you would not know which of the three is out, which came back torn, or how many are on the shelf.
That is why, when you design, you ask: what exactly happens in the world? The member takes an object from the shelf, not a title.
Try it
What is out
The librarian asks which books are out right now and who has them. Show the title, the copy number and the member.
Solution
SELECT b.title, c.id AS copy, m.name
FROM loans l
JOIN copies c ON c.id = l.copy_id
JOIN books b ON b.id = c.book_id
JOIN members m ON m.id = l.member_id
WHERE l.returned_at IS NULL;A loan without returned_at is still out. You go from loans to copies (which copy), from there to books (the title) and to members (who has it). Five copies, including both copies of “Good Omens”.
Exercise
Two tasks
1. Today is 25 October 2026. Who is late? Show the member, the title and the date the book was due.
The loans that have not been returned and are past their due date:
Solution
SELECT m.name, b.title, l.due_at
FROM loans l
JOIN copies c ON c.id = l.copy_id
JOIN books b ON b.id = c.book_id
JOIN members m ON m.id = l.member_id
WHERE l.returned_at IS NULL AND l.due_at < '2026-10-25';Two conditions: the book has not been returned (returned_at IS NULL) and the due date is before today (due_at < '2026-10-25'). Borislav and Galin. Anna has to return hers tomorrow, so she is not late yet.
2. Searching by author in the catalogue shows every book with its authors. Show the title and the author's name.
All books with their authors:
Solution
SELECT b.title, a.name
FROM books b
JOIN book_authors ba ON ba.book_id = b.id
JOIN authors a ON a.id = ba.author_id;You go through the link table book_authors. You get 8 rows for 7 books: “Good Omens” has two authors and appears twice.
Test
Check yourself
Related lessons
Section titled "Related lessons"- Builds on: CREATE TABLE: a new table · Constraints: rules for the data · Foreign keys: links between tables · Relationship types: 1:1, 1:N, M:N
- Continues in: Normalization · The bakery, stage 1: the database and the tables
- Tasks on this topic: Designing a database