Database Relationships
Learn the three types of relationships between tables — one-to-one, one-to-many, and many-to-many — and how to model each in MySQL.
Introduction
Relational databases get their name because tables can be related to one another. Understanding exactly how two tables relate is one of the most important skills in database design — it determines how you write foreign keys, how you JOIN tables, and even whether you need an extra table just to hold the relationship itself.
There are exactly three kinds of relationships you will encounter between any two tables: one-to-one, one-to-many, and many-to-many. This lesson covers all three, with a concrete real-world example for each.
- The three types of relationships between tables.
- A real-world example of each: passports, orders, and courses.
- Why many-to-many relationships require a junction table.
- How to build a junction table like student_courses.
What is a Relationship?
A relationship describes how rows in one table connect to rows in another table, usually through a foreign key. The "shape" of that connection — how many rows on each side can be linked — is what defines the type of relationship.
For any two tables, ask: "for one row in Table A, how many matching rows can exist in Table B — and vice versa?" The answer is always one of: one, many, or many (in both directions).
One-to-One Relationships
In a one-to-one relationship, each row in Table A matches at most one row in Table B, and each row in Table B matches at most one row in Table A. A classic real-world example is a person and their passport — one person has exactly one passport, and one passport belongs to exactly one person.
CREATE TABLE persons (
person_id INT PRIMARY KEY,
name VARCHAR(100)
);
CREATE TABLE passports (
passport_id INT PRIMARY KEY,
person_id INT UNIQUE,
passport_number VARCHAR(20),
FOREIGN KEY (person_id) REFERENCES persons(person_id)
);
INSERT INTO persons VALUES (1, 'Priya');
INSERT INTO passports VALUES (1001, 1, 'X1234567');
SELECT p.name, pp.passport_number
FROM persons p
JOIN passports pp ON p.person_id = pp.person_id;+-------+------------------+
| name | passport_number |
+-------+------------------+
| Priya | X1234567 |
+-------+------------------+The UNIQUE constraint on person_id in the passports table is what enforces "one-to-one" — without it, one person could have multiple passport rows, making it one-to-many instead.
One-to-Many Relationships
In a one-to-many relationship, one row in Table A can match many rows in Table B, but each row in Table B matches only one row in Table A. This is the most common relationship in database design. A customer placing many orders is the textbook example — one customer, many orders, but each order belongs to exactly one customer.
CREATE TABLE customers (
customer_id INT PRIMARY KEY,
name VARCHAR(100)
);
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
order_total DECIMAL(10,2),
FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);
INSERT INTO customers VALUES (1, 'Alex');
INSERT INTO orders VALUES (101, 1, 50.00), (102, 1, 120.00);
SELECT c.name, o.order_id, o.order_total
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id;+------+----------+-------------+
| name | order_id | order_total |
+------+----------+-------------+
| Alex | 101 | 50.00 |
| Alex | 102 | 120.00 |
+------+----------+-------------+Notice that the foreign key (customer_id) lives on the "many" side of the relationship — the orders table — pointing back to the "one" side, customers.
Many-to-Many Relationships
In a many-to-many relationship, many rows in Table A can match many rows in Table B, in both directions. A student can enroll in many courses, and a course can have many students enrolled. Neither table can hold a simple foreign key to the other, because either side could need to reference multiple rows on the other side at once.
If you tried to add a course_id column directly to the students table, each student could only be linked to one course. If you added a student_id column to courses, each course could only be linked to one student. Many-to-many needs a completely separate table to hold the connections.
Building a Junction Table
The solution is a junction table (also called a bridge table or a linking table) — a table whose only job is to store pairs of foreign keys, one row per relationship between the two sides.
CREATE TABLE students (
student_id INT PRIMARY KEY,
name VARCHAR(100)
);
CREATE TABLE courses (
course_id INT PRIMARY KEY,
title VARCHAR(100)
);
-- Junction table linking students and courses
CREATE TABLE student_courses (
student_id INT,
course_id INT,
PRIMARY KEY (student_id, course_id),
FOREIGN KEY (student_id) REFERENCES students(student_id),
FOREIGN KEY (course_id) REFERENCES courses(course_id)
);
INSERT INTO students VALUES (1, 'Priya'), (2, 'Sam');
INSERT INTO courses VALUES (10, 'Mathematics'), (20, 'History');
-- Priya takes both courses, Sam takes only History
INSERT INTO student_courses VALUES (1, 10), (1, 20), (2, 20);Now you can find every course a given student takes, or every student enrolled in a given course, by joining through the junction table in either direction.
SELECT s.name, c.title
FROM students s
JOIN student_courses sc ON s.student_id = sc.student_id
JOIN courses c ON sc.course_id = c.course_id
ORDER BY s.name;+-------+-------------+
| name | title |
+-------+-------------+
| Priya | History |
| Priya | Mathematics |
| Sam | History |
+-------+-------------+Notice PRIMARY KEY (student_id, course_id) uses both columns together. This composite key ensures the same student cannot be enrolled in the same course twice, while still allowing a student to appear in many rows overall.
Choosing the Right Relationship
| Relationship | Example | Foreign Key Location |
|---|---|---|
| One-to-One | Person and passport | Foreign key with a UNIQUE constraint |
| One-to-Many | Customer and orders | Foreign key on the "many" side table |
| Many-to-Many | Students and courses | Junction table holding both foreign keys |
Common Mistakes
- Forgetting the UNIQUE constraint when modeling a one-to-one relationship, which silently allows it to become one-to-many.
- Trying to force a many-to-many relationship using a single foreign key column.
- Forgetting to add a composite primary key (or unique constraint) on the junction table, allowing duplicate relationship rows.
- Not adding foreign key constraints on the junction table, which can let it reference rows that no longer exist.
Best Practices
- Identify the relationship type before writing any table definitions.
- Always place the foreign key on the "many" side of a one-to-many relationship.
- Use a junction table for every many-to-many relationship, with a composite primary key.
- Name junction tables clearly, combining both table names (like student_courses).
Frequently Asked Questions
Can a junction table have its own extra columns?
Yes. For example, student_courses could also store an enrollment_date or a grade for that specific student-course pairing, since that data belongs to the relationship itself, not to either table alone.
Is a one-to-one relationship the same as just merging the two tables?
Not necessarily. You might keep them separate for organizational clarity, security (restricting access to sensitive columns), or because one side is optional for many rows.
How do I know if a relationship is really many-to-many and not one-to-many?
Ask whether a row on either side could reasonably need more than one match on the other side. If a student can take multiple courses AND a course can have multiple students, it is many-to-many.
Can a junction table link more than two tables?
Typically a junction table links exactly two tables, but you can chain multiple junction tables together to model more complex, three-way relationships when needed.
Key Takeaways
- There are three types of table relationships: one-to-one, one-to-many, and many-to-many.
- One-to-one uses a foreign key with a UNIQUE constraint (like a person and their passport).
- One-to-many places the foreign key on the "many" side (like a customer and their orders).
- Many-to-many requires a junction table holding foreign keys to both sides (like students and courses).
- A junction table typically uses a composite primary key across both foreign key columns.
Summary
Every relationship between two tables is one of three shapes: one-to-one, one-to-many, or many-to-many. Recognizing which shape applies tells you exactly where to place your foreign keys, and whether you need a junction table at all.
In this lesson, you learned all three relationship types with real-world examples, and built a student_courses junction table to model a many-to-many relationship. Next, you will learn how to nest one query inside another using subqueries.
- You can identify one-to-one, one-to-many, and many-to-many relationships.
- You know where to place foreign keys for each relationship type.
- You built a junction table to model a many-to-many relationship.
- You are ready to learn about subqueries.