The Demo Database
Every example in this course uses the same small database for an imaginary online shop. Knowing its tables and how they connect will make the rest of the course much easier to follow — come back to this page whenever you need a reminder.
The tables
| Table | Rows | What it holds |
|---|---|---|
customers | 10 | People who have signed up to the shop |
products | 12 | Items for sale, with category, price and stock |
orders | 15 | One row per order: who placed it, when, and its status |
order_items | 23 | The products in each order, with quantity and price paid |
employees | 12 | Staff, with salary, department and manager |
departments | 5 | The company's departments and where they're based |
How the tables connect
customers 1 ──< orders 1 ──< order_items >── 1 products departments 1 ──< employees employees (manager) 1 ──< employees
- A customer can place many orders; each order belongs to one customer (
orders.customer_id). - An order contains many order items; each item refers to one product (
order_items.order_id,order_items.product_id). - A department has many employees (
employees.department_id). - An employee's manager is another employee (
employees.manager_id).
customers
SELECT * FROM customers;
| id | name | city | country | signup_date | |
|---|---|---|---|---|---|
| 1 | Ana Pereira | ana.pereira@example.com | Lisbon | Portugal | 2024-02-11 |
| 2 | Ben Carter | ben.carter@example.com | Manchester | UK | 2024-05-23 |
| 3 | Chloé Martin | chloe.martin@example.com | Lyon | France | 2024-07-02 |
| 4 | David Müller | david.mueller@example.com | Berlin | Germany | 2024-09-15 |
| 5 | Elena García | elena.garcia@example.com | Madrid | Spain | 2025-01-08 |
| 6 | Farah Haddad | farah.haddad@example.com | NULL | France | 2025-03-19 |
| 7 | George Brown | george.brown@example.com | London | UK | 2025-06-30 |
| 8 | Hana Novak | hana.novak@example.com | Prague | Czechia | 2025-08-21 |
| 9 | Isaac Levi | isaac.levi@example.com | Porto | Portugal | 2025-11-04 |
| 10 | Julia Santos | NULL | Lisbon | Portugal | 2026-01-14 |
Notice the gaps: Farah has no city and Julia has no email. Missing values are stored as NULL (lesson 11).
products
SELECT * FROM products;
| id | name | category | price | stock |
|---|---|---|---|---|
| 1 | The Patient Gardener | Books | 24.9 | 40 |
| 2 | Learning SQL Step by Step | Books | 32.5 | 25 |
| 3 | Night Sky Atlas | Books | 45 | 8 |
| 4 | Wireless Earbuds | Electronics | 59.99 | 60 |
| 5 | USB-C Charger | Electronics | 19.99 | 120 |
| 6 | Mechanical Keyboard | Electronics | 89 | 0 |
| 7 | Ceramic Mug | Home | 12.5 | 200 |
| 8 | Desk Lamp | Home | 34 | 15 |
| 9 | Linen Throw | Home | 49 | 30 |
| 10 | Jigsaw Puzzle 1000 | Toys | 18 | 50 |
| 11 | Wooden Train Set | Toys | 39.9 | 12 |
| 12 | Smart Plug | Electronics | 14.99 | 75 |
orders
SELECT * FROM orders;
| id | customer_id | order_date | status |
|---|---|---|---|
| 1 | 1 | 2025-09-03 | delivered |
| 2 | 2 | 2025-09-14 | delivered |
| 3 | 1 | 2025-10-01 | delivered |
| 4 | 3 | 2025-10-20 | delivered |
| 5 | 4 | 2025-11-02 | cancelled |
| 6 | 5 | 2025-11-15 | delivered |
| 7 | 2 | 2025-12-01 | delivered |
| 8 | 7 | 2025-12-12 | delivered |
| 9 | 6 | 2026-01-07 | shipped |
| 10 | 8 | 2026-01-22 | delivered |
| 11 | 1 | 2026-02-03 | shipped |
| 12 | 9 | 2026-02-14 | pending |
| 13 | 3 | 2026-02-20 | pending |
| 14 | 4 | 2026-03-01 | delivered |
| 15 | 7 | 2026-03-05 | pending |
An order's status is one of pending, shipped, delivered or cancelled.
order_items
SELECT * FROM order_items LIMIT 6;
| order_id | product_id | quantity | unit_price |
|---|---|---|---|
| 1 | 1 | 1 | 24.9 |
| 1 | 7 | 2 | 12.5 |
| 2 | 4 | 1 | 59.99 |
| 3 | 2 | 1 | 32.5 |
| 3 | 5 | 2 | 19.99 |
| 4 | 9 | 1 | 49 |
The unit_price is copied from the product when the order is placed, so later price changes don't rewrite history. This table has a composite primary key: the pair (order_id, product_id).
employees and departments
SELECT id, first_name, last_name, department_id, job_title, salary, manager_id FROM employees;
| id | first_name | last_name | department_id | job_title | salary | manager_id |
|---|---|---|---|---|---|---|
| 1 | Olivia | Brandt | NULL | Chief Executive | 150000 | NULL |
| 2 | Rafael | Costa | 1 | Sales Manager | 82000 | 1 |
| 3 | Mei | Tanaka | 2 | Engineering Manager | 98000 | 1 |
| 4 | Jonas | Weber | 2 | Senior Developer | 85000 | 3 |
| 5 | Amara | Okafor | 2 | Developer | 68000 | 3 |
| 6 | Lucas | Ferreira | 1 | Sales Representative | 52000 | 2 |
| 7 | Sofia | Rossi | 1 | Sales Representative | 54000 | 2 |
| 8 | Daniel | Kim | 3 | Marketing Lead | 71000 | 1 |
| 9 | Hannah | Schmidt | 3 | Content Writer | 48000 | 8 |
| 10 | Ethan | Walsh | 4 | Support Lead | 60000 | 1 |
| 11 | Priya | Nair | 4 | Support Agent | 42000 | 10 |
| 12 | Tomás | Silva | 2 | Developer | 68000 | 3 |
SELECT * FROM departments;
| id | name | location |
|---|---|---|
| 1 | Sales | Lisbon |
| 2 | Engineering | Berlin |
| 3 | Marketing | Lisbon |
| 4 | Support | Dublin |
| 5 | Research | NULL |
The chief executive has no department and no manager, and the Research department has no employees yet — details that matter when we reach joins.
The table definitions
This is how the orders table was created. You'll learn to write statements like this in lessons 40–43.
CREATE TABLE orders ( id INTEGER PRIMARY KEY, customer_id INTEGER NOT NULL REFERENCES customers(id), order_date DATE NOT NULL, status TEXT NOT NULL CHECK (status IN ('pending', 'shipped', 'delivered', 'cancelled')) );
Exploring the schema yourself
Every database stores a description of its own tables. In SQLite, it's the sqlite_schema table; most other systems use the standard information_schema views (lesson 52).