By WebNest Studio Engineering Team
Database and SQL Tutorial
Entity-Relationship (ER) Modelling
Entity-Relationship (ER) modelling is a technique for designing a database's structure before writing any SQL, by identifying the real-world "things" a system needs to track, the facts about each thing, and how they relate to one another. An ER diagram is the visual expression of this model, and it typically becomes the direct blueprint for a set of CREATE TABLE statements.
Why it matters
Before writing any SQL you have to decide which tables exist and how they connect. ER modelling is that step: naming the things the system deals with and the relationships between them. A mistake here, such as treating a many-to-many relationship as one-to-many, means rebuilding tables later, when they are full of data.
Entities and Attributes
An entity is a distinct real-world object or concept the database needs to store data about — for example, Customer, Product, or Order. An attribute is a property of an entity, such as a Customer's name and email, or a Product's price. In the relational model, an entity typically becomes a table, and its attributes become that table's columns.
Relationships
A relationship describes how two entities are associated — for example, a Customer "places" an Order, or a Student "enrolls in" a Course. Relationships are what foreign keys implement physically once the model is turned into tables.
Cardinality: One-to-Many and Many-to-Many
Cardinality describes how many instances of one entity can relate to how many instances of another.
- One-to-many (1:N) — one Customer can place many Orders, but each Order belongs to exactly one Customer. Implemented with a foreign key on the "many" side (orders.customer_id).
- Many-to-many (M:N) — one Student can enroll in many Courses, and one Course can have many Students. This cannot be represented with a single foreign key; it requires a separate join (junction) table, such as enrollments(student_id, course_id), with a composite key.
- One-to-one (1:1) — one entity instance relates to exactly one instance of another, such as one Employee having exactly one dedicated ParkingSpot; less common, usually implemented with a unique foreign key.
Example
Turning a one-to-many and a many-to-many relationship into tables
-- One-to-many: one customer -> many orders
CREATE TABLE customers (
id INTEGER PRIMARY KEY,
name VARCHAR(100) NOT NULL
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL REFERENCES customers(id)
);
-- Many-to-many: students <-> courses, via a junction table
CREATE TABLE students (
id INTEGER PRIMARY KEY,
name VARCHAR(100) NOT NULL
);
CREATE TABLE courses (
id INTEGER PRIMARY KEY,
title VARCHAR(120) NOT NULL
);
CREATE TABLE enrollments (
student_id INTEGER REFERENCES students(id),
course_id INTEGER REFERENCES courses(id),
PRIMARY KEY (student_id, course_id)
);
Five tables created; enrollments resolves the many-to-many relationship between students and courses.
Common Mistakes
- Trying to implement a many-to-many relationship by adding a foreign key column directly to one of the two entity tables — a single foreign key column can only express "many-to-one," so a junction table is required instead.
- Confusing an entity (Customer, in general) with an instance of that entity (one specific customer row) when drawing the diagram.
- Skipping ER modelling for anything beyond a trivial schema and going straight to CREATE TABLE, which often produces missing relationships or duplicated data that has to be refactored later.
- Forgetting that the "one" side of a one-to-many relationship never stores the foreign key — the "many" side does (orders references customers, not the reverse).
Exercise
A student can take many courses and a course has many students. Model this with a junction table enrollments whose primary key is the pair of ids, each a foreign key. Then, using the data provided, list the titles of the courses Asha takes, in alphabetical order.
Expected output: title, HTML, Python (one per line)
CREATE TABLE students (id INTEGER PRIMARY KEY, name TEXT);
CREATE TABLE courses (id INTEGER PRIMARY KEY, title TEXT);
-- TODO: create enrollments (student_id, course_id) with a composite primary key
INSERT INTO students (id, name) VALUES (1, 'Asha'), (2, 'Ravi');
INSERT INTO courses (id, title) VALUES (1, 'Python'), (2, 'HTML'), (3, 'SQL');
INSERT INTO enrollments (student_id, course_id) VALUES (1, 1), (1, 2), (2, 3);
-- TODO: the titles of Asha's courses, in alphabetical order
Show hints
- A composite key is declared at the end of the table:
PRIMARY KEY (student_id, course_id). - Join
studentstoenrollmentsandenrollmentstocourses, then filter on the name.
Show solution
CREATE TABLE students (id INTEGER PRIMARY KEY, name TEXT);
CREATE TABLE courses (id INTEGER PRIMARY KEY, title TEXT);
CREATE TABLE enrollments (
student_id INTEGER NOT NULL REFERENCES students(id),
course_id INTEGER NOT NULL REFERENCES courses(id),
PRIMARY KEY (student_id, course_id)
);
INSERT INTO students (id, name) VALUES (1, 'Asha'), (2, 'Ravi');
INSERT INTO courses (id, title) VALUES (1, 'Python'), (2, 'HTML'), (3, 'SQL');
INSERT INTO enrollments (student_id, course_id) VALUES (1, 1), (1, 2), (2, 3);
SELECT c.title
FROM students s
JOIN enrollments e ON e.student_id = s.id
JOIN courses c ON c.id = e.course_id
WHERE s.name = 'Asha'
ORDER BY c.title;
Quick quiz
1. In a one-to-many relationship between customers and orders, where does the foreign key go?
- A. In the customers table
- B. In both tables
- C. In a third table
- D. In the orders table, the "many" side
Show answer
D. Each order stores the id of the one customer it belongs to.
2. How is a many-to-many relationship implemented?
- A. With a junction table holding a foreign key to each side
- B. With a foreign key in one of the two tables
- C. With a comma-separated list of ids in a column
- D. It cannot be implemented
Show answer
A. Each row of the junction table records one pairing.
3. In an ER diagram, what is an entity?
- A. A relationship between tables
- B. A thing the system stores data about, such as a customer
- C. A data type
- D. A query
Show answer
B. Entities usually become tables, and their attributes become columns.
Interview questions
What are the types of relationship between tables?
Show answer
One-to-one: each row in one table relates to at most one row in the other, such as a user and a user profile; implemented with a foreign key that is also unique. One-to-many: one row relates to many rows in the other, such as a customer and orders; the foreign key goes on the many side. Many-to-many: rows on each side relate to many on the other, such as students and courses; implemented with a junction table.
How do you go from requirements to a database schema?
Show answer
Identify the entities, the nouns the system has to remember, and the attributes of each. Identify the relationships between them and the cardinality of each: one-to-one, one-to-many or many-to-many. Draw this as an ER diagram. Then turn entities into tables, attributes into columns with types and constraints, and relationships into foreign keys or junction tables. Finally check the result against the normal forms.
Key Points to Remember
- Entities become tables, and attributes become columns.
- Relationships describe associations between entities and are physically implemented with foreign keys.
- One-to-many relationships use a single foreign key on the "many" side; many-to-many relationships require a junction table with a composite key.
- ER modelling before writing SQL catches structural mistakes early, when they are cheap to fix.
Practice in the playground
Write and run your own code for this topic, or start from the exercise or an example. Runs your SQL on SQLite in your browser. Standard SQL works; a few features that exist only in PostgreSQL or MySQL do not. Your code for each topic is kept in this browser.
Run the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.
These examples need a project environment on your computer, so they can be copied but not run here. Codelab runs Python, FastAPI backends with SQLite, plain Java 17 and HTML/CSS/JavaScript.
Written by
WebNest Studio Engineering Team
Practical lessons from developers working with Java, Python, React, databases and production systems.
Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering