373 lines
8.5 KiB
Markdown
373 lines
8.5 KiB
Markdown
# Les 8: Database Principles
|
|
|
|
---
|
|
|
|
## Hoofdstuk
|
|
**Deel 2: Technical Foundations** (Les 5-9)
|
|
|
|
## Beschrijving
|
|
Leer de basisprincipes van relationele databases voordat we Supabase gaan gebruiken. Begrijp tabellen, relaties, keys en normalisatie - essentiële kennis voor elke developer.
|
|
|
|
---
|
|
|
|
## Te Behandelen
|
|
|
|
### Wat is een Relationele Database?
|
|
|
|
**Een database is:** Een georganiseerde verzameling van data.
|
|
|
|
**Relationeel betekent:** Data is opgeslagen in tabellen die aan elkaar gerelateerd zijn.
|
|
|
|
**Vergelijk het met Excel:**
|
|
- Database = Excel workbook
|
|
- Tabel = Excel sheet
|
|
- Kolom = Excel kolom (field)
|
|
- Rij = Excel rij (record)
|
|
|
|
---
|
|
|
|
### Tabellen, Kolommen en Rijen
|
|
|
|
**Voorbeeld: Users tabel**
|
|
|
|
| id | name | email | created_at |
|
|
|----|------|-------|------------|
|
|
| 1 | Tim | tim@email.com | 2024-01-15 |
|
|
| 2 | Anna | anna@email.com | 2024-01-16 |
|
|
| 3 | Jan | jan@email.com | 2024-01-17 |
|
|
|
|
**Terminologie:**
|
|
- **Tabel:** users
|
|
- **Kolommen:** id, name, email, created_at
|
|
- **Rijen:** 3 records (Tim, Anna, Jan)
|
|
- **Cell:** Eén specifieke waarde (bijv. "tim@email.com")
|
|
|
|
---
|
|
|
|
### Data Types
|
|
|
|
Elke kolom heeft een type:
|
|
|
|
| Type | Beschrijving | Voorbeeld |
|
|
|------|--------------|-----------|
|
|
| `text` / `varchar` | Tekst | "Tim", "Hello world" |
|
|
| `integer` / `int` | Hele getallen | 1, 42, -5 |
|
|
| `decimal` / `numeric` | Decimalen | 19.99, 3.14 |
|
|
| `boolean` | True/False | true, false |
|
|
| `timestamp` | Datum + tijd | 2024-01-15 14:30:00 |
|
|
| `uuid` | Unieke identifier | a1b2c3d4-e5f6-... |
|
|
|
|
**Kies het juiste type:**
|
|
- Prijs? → `decimal` (niet `integer`, want centen)
|
|
- Is actief? → `boolean`
|
|
- Naam? → `text`
|
|
- Aantal? → `integer`
|
|
|
|
---
|
|
|
|
### Primary Keys
|
|
|
|
**Wat:** Een kolom die elke rij UNIEK identificeert.
|
|
|
|
**Regels:**
|
|
- Moet uniek zijn per rij
|
|
- Mag nooit NULL zijn
|
|
- Verandert nooit
|
|
|
|
**Voorbeeld:**
|
|
```
|
|
users
|
|
------
|
|
id (PRIMARY KEY) | name | email
|
|
1 | Tim | tim@email.com
|
|
2 | Anna | anna@email.com
|
|
```
|
|
|
|
**Waarom niet `email` als primary key?**
|
|
- Emails kunnen veranderen
|
|
- `id` is stabiel en snel
|
|
|
|
---
|
|
|
|
### Foreign Keys
|
|
|
|
**Wat:** Een kolom die verwijst naar de primary key van een andere tabel.
|
|
|
|
**Voorbeeld: Posts tabel**
|
|
```
|
|
posts
|
|
------
|
|
id | title | user_id (FOREIGN KEY → users.id)
|
|
1 | "Mijn blog" | 1
|
|
2 | "Hello world" | 1
|
|
3 | "Tips" | 2
|
|
```
|
|
|
|
**Wat zegt dit?**
|
|
- Post 1 en 2 zijn van user 1 (Tim)
|
|
- Post 3 is van user 2 (Anna)
|
|
|
|
---
|
|
|
|
### Relatie Types
|
|
|
|
**One-to-Many (1:N)** - Meest voorkomend!
|
|
```
|
|
Eén user → meerdere posts
|
|
Eén category → meerdere products
|
|
```
|
|
|
|
**One-to-One (1:1)** - Zeldzaam
|
|
```
|
|
Eén user → één profile
|
|
```
|
|
|
|
**Many-to-Many (N:N)** - Via tussentabel
|
|
```
|
|
Posts ↔ Tags (een post heeft meerdere tags, een tag heeft meerdere posts)
|
|
```
|
|
|
|
---
|
|
|
|
### One-to-Many Voorbeeld
|
|
|
|
```
|
|
users posts
|
|
------ ------
|
|
id | name id | title | user_id
|
|
1 | Tim ←────────── 1 | "Blog 1" | 1
|
|
2 | Anna ←────┬───── 2 | "Blog 2" | 1
|
|
└───── 3 | "Tips" | 2
|
|
```
|
|
|
|
**Lees:** Tim heeft 2 posts, Anna heeft 1 post.
|
|
|
|
---
|
|
|
|
### Many-to-Many met Tussentabel
|
|
|
|
```
|
|
posts post_tags tags
|
|
------ --------- ------
|
|
id | title post_id | tag_id id | name
|
|
1 | "React tips" 1 | 1 1 | "react"
|
|
2 | "CSS guide" 1 | 2 2 | "frontend"
|
|
2 | 2 3 | "css"
|
|
2 | 3
|
|
```
|
|
|
|
**Lees:**
|
|
- Post 1 heeft tags: react, frontend
|
|
- Post 2 heeft tags: frontend, css
|
|
|
|
---
|
|
|
|
### Normalisatie Basics
|
|
|
|
**Probleem: Data duplicatie**
|
|
```
|
|
orders (SLECHT)
|
|
------
|
|
id | customer_name | customer_email | product_name | price
|
|
1 | Tim | tim@email.com | Laptop | 999
|
|
2 | Tim | tim@email.com | Phone | 699
|
|
3 | Anna | anna@email.com | Laptop | 999
|
|
```
|
|
|
|
**Problemen:**
|
|
- Tim's email staat 2x (als hij verandert: 2 plekken updaten)
|
|
- "Laptop" en prijs staan 2x
|
|
|
|
---
|
|
|
|
### Genormaliseerde Versie
|
|
|
|
```
|
|
users products orders
|
|
------ -------- ------
|
|
id | name | email id | name | price id | user_id | product_id
|
|
1 | Tim | tim@... 1 | Laptop | 999 1 | 1 | 1
|
|
2 | Anna | anna@... 2 | Phone | 699 2 | 1 | 2
|
|
3 | 2 | 1
|
|
```
|
|
|
|
**Voordelen:**
|
|
- Elk gegeven staat 1x
|
|
- Update op 1 plek
|
|
- Minder opslagruimte
|
|
|
|
---
|
|
|
|
### NULL Values
|
|
|
|
**NULL = "geen waarde" (niet 0, niet "")**
|
|
|
|
```
|
|
users
|
|
------
|
|
id | name | phone
|
|
1 | Tim | 0612345678
|
|
2 | Anna | NULL ← Geen telefoon bekend
|
|
```
|
|
|
|
**Wanneer NULL toestaan?**
|
|
- Optionele velden (phone, description)
|
|
- Niet bij verplichte velden (name, email)
|
|
|
|
---
|
|
|
|
### Defaults
|
|
|
|
**Automatische waarde als je niks opgeeft:**
|
|
|
|
```
|
|
todos
|
|
------
|
|
id | title | completed | created_at
|
|
| | DEFAULT: false | DEFAULT: now()
|
|
```
|
|
|
|
Bij `INSERT INTO todos (title) VALUES ('Test')`:
|
|
```
|
|
id | title | completed | created_at
|
|
1 | Test | false | 2024-01-15 10:30:00
|
|
```
|
|
|
|
---
|
|
|
|
### Database Schema Tekenen
|
|
|
|
**Tools:** draw.io, Excalidraw, pen en papier
|
|
|
|
**Conventie:**
|
|
```
|
|
┌──────────────┐ ┌──────────────┐
|
|
│ users │ │ posts │
|
|
├──────────────┤ ├──────────────┤
|
|
│ id (PK) │───┐ │ id (PK) │
|
|
│ name │ │ │ title │
|
|
│ email │ └────→│ user_id (FK) │
|
|
│ created_at │ │ content │
|
|
└──────────────┘ │ created_at │
|
|
└──────────────┘
|
|
```
|
|
|
|
PK = Primary Key
|
|
FK = Foreign Key
|
|
Pijl = Relatie richting
|
|
|
|
---
|
|
|
|
## Tools
|
|
- Pen en papier / Excalidraw / draw.io
|
|
- Supabase Table Editor (vooruitblik)
|
|
|
|
---
|
|
|
|
## Lesopdracht (2 uur)
|
|
|
|
### Database Design Oefening
|
|
|
|
**Deel 1: Blog Database Ontwerpen (45 min)**
|
|
|
|
Ontwerp een database voor een blog met:
|
|
- Users (kunnen posts schrijven)
|
|
- Posts (hebben een auteur)
|
|
- Comments (op posts, door users)
|
|
|
|
Voor elke tabel:
|
|
1. Teken de tabel met kolommen
|
|
2. Bepaal data types
|
|
3. Markeer Primary Keys
|
|
4. Markeer Foreign Keys
|
|
5. Teken de relaties
|
|
|
|
**Deel 2: Normalisatie Oefening (30 min)**
|
|
|
|
Gegeven deze "slechte" tabel:
|
|
|
|
```
|
|
library
|
|
-------
|
|
book_title | author_name | author_email | borrower_name | borrowed_date
|
|
"1984" | "Orwell" | orwell@... | "Tim" | 2024-01-15
|
|
"1984" | "Orwell" | orwell@... | "Anna" | 2024-01-10
|
|
"Dune" | "Herbert" | herbert@... | "Tim" | 2024-01-12
|
|
```
|
|
|
|
Normaliseer naar aparte tabellen:
|
|
1. Welke entiteiten zie je?
|
|
2. Maak aparte tabellen
|
|
3. Voeg relaties toe
|
|
|
|
**Deel 3: Eindproject Schema (45 min)**
|
|
|
|
Ontwerp het database schema voor jouw eindproject:
|
|
1. Welke entiteiten heb je nodig?
|
|
2. Teken elke tabel met kolommen
|
|
3. Bepaal relaties
|
|
4. Documenteer je keuzes
|
|
|
|
### Deliverable
|
|
- Blog database schema (tekening)
|
|
- Genormaliseerde library database
|
|
- Eindproject database schema
|
|
|
|
---
|
|
|
|
## Huiswerk (2 uur)
|
|
|
|
### Verdieping en Voorbereiding
|
|
|
|
**Deel 1: Eindproject Schema Uitwerken (1 uur)**
|
|
|
|
Werk je database schema volledig uit:
|
|
|
|
1. **Per tabel:**
|
|
- Naam
|
|
- Alle kolommen met data types
|
|
- Primary key
|
|
- Foreign keys
|
|
- Defaults
|
|
- Nullable fields
|
|
|
|
2. **Documenteer:**
|
|
- Waarom deze structuur?
|
|
- Welke relaties?
|
|
- Eventuele alternatieve overwegingen
|
|
|
|
**Deel 2: Supabase Account (30 min)**
|
|
|
|
Bereid je voor op volgende les:
|
|
1. Maak account op [supabase.com](https://supabase.com)
|
|
2. Verken de interface
|
|
3. Bekijk de Table Editor
|
|
|
|
**Deel 3: Reflectie (30 min)**
|
|
|
|
Beantwoord deze vragen (kort):
|
|
1. Wat is het verschil tussen primary en foreign key?
|
|
2. Waarom normaliseren we data?
|
|
3. Wanneer gebruik je one-to-many vs many-to-many?
|
|
4. Welke tabellen heeft jouw eindproject nodig?
|
|
|
|
### Deliverable
|
|
- Volledig uitgewerkt database schema voor eindproject
|
|
- Supabase account aangemaakt
|
|
- Reflectie vragen beantwoord
|
|
|
|
---
|
|
|
|
## Leerdoelen
|
|
Na deze les kan de student:
|
|
- Uitleggen wat een relationele database is
|
|
- Tabellen, kolommen en rijen beschrijven
|
|
- De juiste data types kiezen
|
|
- Primary keys en hun doel uitleggen
|
|
- Foreign keys en relaties begrijpen
|
|
- One-to-many en many-to-many relaties herkennen
|
|
- Het probleem van data duplicatie identificeren
|
|
- Een database normaliseren
|
|
- NULL values en defaults begrijpen
|
|
- Een database schema ontwerpen en tekenen
|