Add joins lesson

feat/course
Kamran Ahmed 3 weeks ago
parent 411908dcee
commit 973d422a49
  1. 180
      src/data/courses/sql-mastery/chapters/multi-table-queries/lessons/foreign-key-constraint.md
  2. 125
      src/data/courses/sql-mastery/chapters/multi-table-queries/lessons/joins-in-queries.md
  3. 4
      src/data/courses/sql-mastery/chapters/multi-table-queries/lessons/relationships-and-types.md

@ -0,0 +1,180 @@
---
title: Foreign Key Constraint
description: Learn how foreign keys are used to enforce relationships between tables
order: 130
type: lesson-challenge
---
In our previous lessons, we learned about relationships between tables and how they are achieved using primary and foreign keys.
Now, let's explore how to enforce these relationships using foreign key constraints.
## What is a Foreign Key Constraint?
A foreign key constraint is a rule that ensures referential integrity between two tables. It prevents actions that would destroy relationships between tables or create invalid references.
### What is referential integrity?
Referential integrity is the idea that data
Let's use our bookstore example to understand foreign key constraints:
```sql
CREATE TABLE books (
id INTEGER PRIMARY KEY,
title VARCHAR(255) NOT NULL,
price DECIMAL(10, 2)
);
CREATE TABLE sales (
id INTEGER PRIMARY KEY,
book_id INTEGER,
quantity INTEGER,
sale_date DATE,
FOREIGN KEY (book_id) REFERENCES books(id)
);
```
In this example:
- The `book_id` column in the `sales` table is a foreign key
- It references the `id` column in the `books` table
- The foreign key constraint ensures that every `book_id` in `sales` must exist in the `books` table
### Alternative Syntax
Just like other constraints, you can also define foreign keys using different syntaxes:
```sql
-- Using CONSTRAINT keyword to name the foreign key
CREATE TABLE sales (
id INTEGER PRIMARY KEY,
book_id INTEGER,
quantity INTEGER,
sale_date DATE,
CONSTRAINT fk_book
FOREIGN KEY (book_id)
REFERENCES books(id)
);
-- Inline syntax
CREATE TABLE sales (
id INTEGER PRIMARY KEY,
book_id INTEGER REFERENCES books(id),
quantity INTEGER,
sale_date DATE
);
```
## How Foreign Keys Maintain Data Integrity
Foreign keys prevent several types of invalid operations:
### 1. Inserting Invalid References
```sql
-- This will fail if book_id=999 doesn't exist in books table
INSERT INTO sales (book_id, quantity, sale_date)
VALUES (999, 1, '2024-03-20');
```
### 2. Deleting Referenced Records
By default, you cannot delete a record from the parent table if it's referenced in the child table:
```sql
-- This will fail if any sales reference this book
DELETE FROM books WHERE id = 1;
```
### 3. Updating Referenced Keys
Similarly, you cannot update a primary key if it's referenced by other tables:
```sql
-- This will fail if any sales reference this book
UPDATE books SET id = 999 WHERE id = 1;
```
## ON DELETE and ON UPDATE Clauses
You can specify what happens when a referenced record is deleted or updated using `ON DELETE` and `ON UPDATE` clauses:
```sql
CREATE TABLE sales (
id INTEGER PRIMARY KEY,
book_id INTEGER,
quantity INTEGER,
sale_date DATE,
FOREIGN KEY (book_id)
REFERENCES books(id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
```
Available options include:
| Option | Description |
| ----------- | --------------------------------------------------- |
| CASCADE | Automatically delete/update related records |
| SET NULL | Set the foreign key to NULL |
| SET DEFAULT | Set the foreign key to its default value |
| RESTRICT | Prevent the deletion/update (this is the default) |
| NO ACTION | Similar to RESTRICT, but checked at different times |
### Example with Multiple Options
```sql
CREATE TABLE books (
id INTEGER PRIMARY KEY,
author_id INTEGER,
title VARCHAR(255),
FOREIGN KEY (author_id)
REFERENCES authors(id)
ON DELETE SET NULL -- If author is deleted, set author_id to NULL
ON UPDATE CASCADE -- If author_id changes, update it here too
);
```
## Composite Foreign Keys
Just like primary keys, foreign keys can also consist of multiple columns:
```sql
CREATE TABLE book_editions (
book_id INTEGER,
edition_number INTEGER,
publisher_id INTEGER,
publication_year INTEGER,
PRIMARY KEY (book_id, edition_number),
FOREIGN KEY (book_id, edition_number)
REFERENCES books(id, edition)
);
```
## Best Practices
1. **Always Name Your Constraints**: This makes error messages more meaningful and maintenance easier:
```sql
CONSTRAINT fk_book_author
FOREIGN KEY (author_id)
REFERENCES authors(id)
```
2. **Consider Indexing**: Foreign key columns are often used in JOIN operations, so consider adding indexes:
```sql
CREATE INDEX idx_book_author ON books(author_id);
```
3. **Choose ON DELETE/UPDATE Actions Carefully**:
- Use `CASCADE` when child records cannot exist without parent
- Use `SET NULL` when child records can exist independently
- Use `RESTRICT` when you want to prevent accidental deletions
4. **Maintain Data Consistency**: Always insert parent records before child records and remove child records before parent records.
In the next lesson, we'll learn how to query data across multiple tables using these relationships.

@ -0,0 +1,125 @@
---
title: JOINs in Queries
description: Learn how to query data across multiple tables using joins
order: 120
type: lesson-challenge
setup: |
```sql
CREATE TABLE author (
id INT PRIMARY KEY,
name VARCHAR(255)
);
CREATE TABLE author_biography (
id INT PRIMARY KEY,
author_id INT,
biography TEXT
);
INSERT INTO author (id, name)
VALUES (1, 'John Doe'),
(2, 'Jane Smith'),
(3, 'Alice Johnson'),
(4, 'Bob Brown');
INSERT INTO author_biography (id, author_id, biography)
VALUES (1, 4, 'Bob Brown\'s biography'),
(2, 3, 'Alice Johnson\'s biography'),
(3, 2, 'Jane Smith\'s biography'),
(4, 1, 'John Doe\'s biography');
```
---
So far in this course, we have been mainly writing single-table queries. However, our previous lesson should have given you an idea of how data might not always be stored in a single table.
In this lesson, we will look at how to query data from multiple tables.
## What is a JOIN?
JOINs help us query data from multiple tables based on a related column between them. The result of a JOIN is a new table with related data and columns from all the tables that were joined.
Let's take an example to understand this better. Given the following two tables `author` and `author_biography`:
[![](https://assets.roadmap.sh/guest/author-biography-8evoz.png)](https://assets.roadmap.sh/guest/author-biography-8evoz.png)
Notice how `author_id` in the `author_biography` helps us relate each biography to an author. We can use this relationship to join the two tables and get each author along with their biography.
To do this, we can use the `JOIN` clause.
```sql
SELECT *
FROM author
JOIN author_biography ON author.id = author_biography.author_id;
-- ---------^------ ------------------^--------------------
-- Table to join with Join condition to find matching rows
```
This query will return the following result set:
[![](https://assets.roadmap.sh/guest/author-join-biography-r5jtd.png)](https://assets.roadmap.sh/guest/author-join-biography-r5jtd.png)
Notice how the relevant biographies from `author_biography` are placed next to the relevant rows from the `author` table.
> I would encourage you to try this query out in the editor and see how it works.
### Selecting Specific Columns
If we only want to get the author id, name and biography, we can do so by selecting the relevant columns from the joined table.
```sql
SELECT author.id, author.name, author_biography.biography
FROM author
JOIN author_biography ON author.id = author_biography.author_id;
```
The output from this query will be:
| id | name | biography |
| --- | ------------- | ------------------------- |
| 4 | Bob Brown | Bob Brown's biography |
| 3 | Alice Johnson | Alice Johnson's biography |
| 2 | Jane Smith | Jane Smith's biography |
| 1 | John Doe | John Doe's biography |
The way this query works as follows:
**Step 1** `author` and `author_biography` are joined by verifying the `ON` condition i.e. `author.id = author_biography.author_id`.
![](https://assets.roadmap.sh/guest/step1-joining-tables-t9ms5.png)
**Step 2** Intermediate result is created with data from both tables.
![](https://assets.roadmap.sh/guest/step2-joined-tables-hf315.png)
**Step 3** Columns are returned based on `SELECT` clause.
![](https://assets.roadmap.sh/guest/step3-result-zhqzl.png)
Let's take the same example our bookstore from our previous lesson. Among the tables we had in our bookstore, we had `customer` and `sale`. Here is some data we have in both tables respectively:
| id | name | email | phone |
| --- | ------------- | ------------------------- | ---------- |
| 1 | John Doe | john.doe@example.com | 1234567890 |
| 2 | Jane Smith | jane.smith@example.com | 0987654321 |
| 3 | Alice Johnson | alice.johnson@example.com | 1122334455 |
| 4 | Bob Brown | bob.brown@example.com | 9988776655 |
| 5 | Charlie Davis | charlie.davis@example.com | 1231231230 |
| id | customer_id | book_id | quantity | price | date |
| --- | ----------- | ------- | -------- | ------ | ---------- |
| 1 | 1 | 1 | 2 | 20.00 | 2024-01-01 |
| 2 | 2 | 2 | 3 | 45.00 | 2024-01-02 |
| 3 | 2 | 1 | 1 | 10.00 | 2024-02-03 |
| 4 | 1 | 1 | 1 | 10.00 | 2024-02-04 |
| 5 | 1 | 1 | 2 | 20.00 | 2024-02-05 |
| 6 | 5 | 3 | 1 | 30.00 | 2024-02-06 |
| 7 | 4 | 3 | 4 | 120.00 | 2024-02-07 |
| 8 | 3 | 4 | 1 | 25.00 | 2024-02-08 |
| 9 | 3 | 4 | 1 | 25.00 | 2024-02-09 |
| 10 | 5 | 4 | 2 | 50.00 | 2024-02-10 |
Notice how the `sale` table has a `customer_id` column that references the `id` column in the `customer` table. This is a relationship between the two tables.
We can use this relationship to query data from both tables.

@ -7,7 +7,7 @@ type: lesson
In the previous lesson, we explored how relational databases store data in tables and how entities and attributes are defined. Now, let's delve deeper into the types of relationships that can exist between these entities and how they are represented.
Let's take the same example of our bookstore. Here are different entities we have in our bookstore:
For example, let's say we have a database for a bookstore. We have the following entities:
| Entity Name | Description |
| -------------------- | -------------------------------------------------------------------------------------------------------- |
@ -104,4 +104,4 @@ The complete ER diagram after adding the attributes is shown below:
[![](https://assets.roadmap.sh/guest/complete-bookstore-erd-vb0fp.png)](https://assets.roadmap.sh/guest/complete-bookstore-erd-vb0fp.png)
In the next lesson, we will look at foreign keys and how they are used to enforce relationships between tables. We will also look at some of the DML operations we can perform on multiple tables.
In the next lesson, we will look at how to query data across multiple tables using joins.
Loading…
Cancel
Save