# 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