Databases en SQL
================

*Versie {{ versie }}. Jouw docent: {{ docent }} ({{ docent_email }})*

- Deadline voor het inleveren van de eindopdrachten: **{{ deadline }}**
- Deadline voor het aanvragen van uitstel: **{{ deadline_uitstel_aanvragen }}**
- Uitgestelde deadline: **{{ deadline_uitstel }}**
- Inleveren via: https://app.q-highschool.nl/

## Let op:

Deze syllabus wordt opnieuw gemaakt tijdens blok 1 van 2025-2026.
Deze wordt dus nog aangevuld met de tweede eindopdracht.

Inhoudsopgave:

```{tableofcontents}
```

# Uitleg over inleveropdrachten

Welkom bij een informaticamodule van de Q-highschool!


## Zelfstandig werken en bronnen vermelden
De volgende uitgangspunten gelden voor deze module:

- Je maakt de opdracht zelf
- Als je iets overneemt van een boek of internet, doe je dat met bronvermelding
- Je werk is overzichtelijk en netjes

## Opdrachten met broncode
Informatica heeft vaak opdrachten met broncode, vormen van programmeerwerk.

- Je levert een bestand dat in voor computers en voor mensen leesbaar is
	- Let daarom goed op de instructies bij de opdracht
	
## Meerdere bestanden inleveren

- Maak een mapje met daarin de bestanden
- Maak van dat mapje een zip-bestand
- Lever het zip-bestand in via: https://app.q-highschool.nl/ 

# Inhoud van deze module, wat ga je leren

Aan het eind van deze module:

- Weet je wat een databases is, specifiek richten we ons op zogenaamde relationele databases
- Kun je gegevens opzoeken in een database met de vraag-taal SQL
- Kun je een eenvoudig datamodel ontwerpen
- Weet je dat er meer soorten database zijn dan alleen relationele databases (NoSQL)
- En bonus: we praten ook even over databases en regels

# De eindopdrachten

Er zijn bij deze module twee zaken die je moet inleveren:

1. Werken met queries in het systeem dat de docent heeft gemaakt, zie [de query-taal SQL]
2. Het maken van een database-ontwerp, meer informatie vind je ....

# Wat is een (relationele) database

> Een database is een systeem dat gegevens opslaat en doorzoekbaar maakt

Een database is een computersysteem dat gegevens opslaat op een gestructureerde
manier. Een goed ontworpen database maakt het mogelijk gegevens weer snel en
efficient terug te kunnen vinden. En niet 'een gokje' te doen naar die gegevens
(zoals google of een AI), maar *exact* de juiste gegevens terugvindt.

Een database heeft daarom intern een structuur die lijkt op een excel-sheet:
het heeft *tabellen* met daarin kolommen en rijen.


Waar bestaan databases? Overal waar computers zijn. Bijna elke app in je
telefoon heeft waarschijnljk een database. Chat apps bijvoorbeeld voor al je
chats en contacten. Je telefoon voor al je contacten met een telefoonnummer.

Een betaal-en-bankieren-app heeft contact met een centrale database van de bank
om te weten wat het saldo is en wat er met je geld is gebeurd.

Een school heeft databases voor het bijhouden van leerlingen, klassen, cijfers,
    vakken, docenten etc.

Niet elk van deze tabellen is een relationele database waarmee we kennis maken
in deze module, al zal het je verbazen hoeveel dat er wel zijn.

> Voor wie dieper wil duiken: zoek SQLite op. De website is underwhelming maar
> er zijn letterlijk duizend miljard (een miljoen keer een miljoen) sqlite
> databases actief op de wereld

## Garanties van (relationele) databases

Databases worden door software ontwikkelaars gezien als "betrouwbaar". Dat
betekent dat ze de database zien als een systeem dat als het ware altijd gelijk
heeft. Dit komt door de manier waarop we databases ontwerpen, maar ook door wat
database systemen bieden: garanties.


### Garantie 1: iets gebeurt helemaal, of helemaal niet (atomic)

Als je vraagt aan een database om iets toe te voegen, verwijderen of bij te
werken, dan gebeurt dat ofwel compleet, ofwel helemaal niet. Hierdoor weet je
zeker dat de inhoud van de database altijd 'sense' maakt.

### Garantie 2: consistent

Bij het ontwerpen en inrichten van een database vertellen we zoveel mogelijk
aan de database wat de spelregels zijn. Dit noemen we **constraints**, in het
Nederlands **beperkingen**. De database zal die constraints bewaken en alleen
een actie afmaken als de constraints dat toelaten.

### Garantie 3: isolation

Grotere systemen hebben vaak meerdere gebruikers tegelijk. En voor die
gebruikers worden onafhankelijk van elkaar acties uitgevoerd op de database. De
database houdt wijzigingen onzichtbaar voor de ander, totdat die zeker is dat
alles consistent is en veilig kan worden doorgevoerd.

Je kunt in een database meerdere acties bundelen in een **transaction**, die allemaal als 'atomair' (zie boven) worden gezien en dus allemaal samen doorgaan, of niet doorgaan.

### Garantie 4: durability (duurzaamheid)

Een database geeft pas aan dat een actie klaar is, als die er zeker van is dat
de actie onherroepelijk is uitgevoerd. Dus als direct daarna de stroom uitvalt,
dan heeft de database het resultaat opgeslagen op de vaste opslag. Komt de
database weer terug, dan kun je er zeker van zijn dat de data er is.


### Gevolgen van garanties

Een voordeel kan nadelen met zich meebrengen.

Een database kan rijen of soms zelfs hele tabellen op slot zetten, totdat een actie
klaar is. Dit kan betekenen dat andere processen moeten wachten tot dat slot
eraf is. Dit kan zorgen voor vertraging. Sterker nog: soms wachten processen op zo'n manier op elkaar
dat ze geen ban allen meer vooruit komen. Dat heet een **deadlock**.

En de laatste garantie heeft ook een nadeel. Een database *moet* gegevens
wegschrijven naar de vaste opslag. Dat is niet altijd efficient.
Besturingssytemen van computer willen dat graag optimaliseren en soms even
wachten met gegevens wegschrijven. 

# Hoe werkt een **relationele** database

> Een tabel is als een excelsheet, met precieze kolommen en rijen

Een tabel (todo: plaatje) ziet er uit als een excel-sheet. Er is wel een
belangrijk verschil. Excel laat je toe om willekeurig wat in de vakjes te
zetten. Een database laat dat niet toe.

Elk **rij** in een tabel is een een **record**, een 'vastlegging'. Deze rij
vertegenwoordigt precies 1 ding in de "werkelijkheid" van het systeem.
Bijvoorbeeld een product op een website. Of een speler in een spel. Of een
rekening in een banksysteem.

Elke tabel heeft vaste, **kolommen**. Deze kolommen zijn de eigenschappen van
de records in de tabel.


Enkele voorbeelden:

### Een gebouw heeft een nummer en een naam

| Gebouw | |
|----|---------------------|
| **id** | **naam**        |
| 1 | Kasteel op de heuvel |
| 2 | Ziekenhuis           |

De reden om een nummer toe te voegen is om, onafhankelijk van de inhoud, altijd een uniek kenmerk te hebben per rij.
Daar zijn technische redenen voor, onder andere omdat computers sneller kunnen rekenen met getallen dan met tekst.


### Een bank met gebruiker, rekening, transacties

(todo: maak voorbeeld-tabellen)

## Begrippen

- Tabel
- Rij
- Kolom



# De vraag-taal SQL

> SQL: Een studievriend van de docent noemde het ooit *silly question
> language*, die grap mag je van harte overnemen!

## SQL: structured query language

Al sinds het begin van de informatica is er een zoektocht naar programmeertalen
die 'makkelijk' zijn. Dit zodat meer mensen met computers kunnen werken. Zeker
in de tijd dat er nog geen touch-screens en zelfs nog geen computermuis bestond
was dit erg lastig. Laat staan de AI's van nu!

De essentie van SQL is dat je de database laat weten *wat* je wil zien, maar niet *hoe* die dat moet gaan vinden. 

Alle kolommen laten zien van de tabel `docent`:
```sql
select * from docent;

```
Al mijn uitleg en de eerste inleveropdracht vind je op de website: [Sjaaq](https://sql.merijn.xyz)
het systeem waar je queries kunt uitvoeren en maken. Dat systeem slaat je antwoorden op en op die manier zijn ze ook meteen ingeleverd, handig!


# Sleutels en relaties

Deze module gaat over _relationele_ databases. Dat betekent dat tabellen in een database een relatie kunnen hebben met andere tabellen.

> `¯\_(ツ)_/¯` Het database systeem _postgres_ noemt een _tabel_ een _relation_, dus als je een fout maakt zie je soms 'relation ... does not exist' of zoiets; dan bedoelt postgres een tabel. Naar _mijn_ mening is dat incorrect gebruik van de term relatie; dat is iets tussen twee tabellen. Vind ik.


## Sleutels

Elke rij in een tabel is de vastlegging (een record) van een feit, ding, gebeurtnis etc. Dat zou een 'uniek' iets moeten zijn.
Zouden we leerlingen alleen met voornaam opslaan dan krijgen we al gauw een probleem. Zelfs de combinatie van voor- en achternaam *en* geboortedatum is niet altijd uniek. (De docent heeft een vriend die hier daadwerkelijk last van heeft gehad!). Om die reden is het handig een _technische_ unieke identificatie-kolom te maken. Die noemen we vaak `id`:


| Docent | | |
|----|--------|------------|
| *id* | *voornaam*   | *achternaam* |
|----|--------|------------|
| 1  | Merijn | Vogel      |
| 2  | Arthur | Rump       |
| 3  | Pieter | van Engelen|
| 4  | Karen  | van Wichen |


Zo'n kolom heet `primary key`, de belangrijkste sleutel, van de tabel. Een tabel kan maximaal 1 primary key hebben.

Bij het aanmaken van een tabel met SQL, vertellen we dit ook aan de database:

```sql
CREATE table Vrienden ( id int PRIMARY KEY, naam VARCHAR, Geboortedatum DATETIME);
```


Stel we maken een tweede tabel met parcoursen:

| Parcours |  |
|----|--------|
| *id* | *naam*   |
|----|--------|
| 100  | Informatica | 
| 101  | Filosofie | 


Deze heeft ook een primary key.

## Relatie

Nu willen we graag docenten en parcoursen aan elkaar koppelen.
Voor het gemak gaan we ervanuit dat elke docent maar 1 module kan geven. We kunnen dan de tabel van docenten uitbreiden:

| Docent |    |            |     |
|----|--------|------------|-----|
| *id* | *voornaam*   | *achternaam* | *parcours_id* |
|----|--------|------------|--------|
| 1  | Merijn | Vogel      | 101 |
| 2  | Arthur | Rump       | 101 |
| 3  | Pieter | van Engelen| 101 |
| 4  | Karen  | van Wichen | 102 |

We noemen hier niet de naam van de module, maar we verwijzen naar de _primary key_ van de tabel _parcours_. Dit legt de _relatie_ vast tussen de twee tabellen.
Door te wijzen naar de _primary key_ van de andere tabel helpen we de database: deze kan efficient de gegevens bij elkaar halen.


Dit kunnen we aan SQL vertellen op bijvoorbeeld de volgende manier:

```sql
alter table Docent add column parcours_id int references Parcours(id);
```

De kolom *parcours_id* heet een _foreign key_: de primaire sleutel van een _andere_ (foreign) tabel.

> De relatie tussen twee tabellen loopt via de _primaire sleutel_ van een van de twee tabellen. Een rij in een tabel verwijst naar de _id_-kolom van de tabel waar die een relatie mee heeft.


In een plaatje:

![Plaatje van twee tabellen met een relatie](images/db-relaties-20250918.drawio.png)

Databases zullen een relatie afdwingen: je kunt alleen nieuwe rijen toevoegen die aan de relatie voldoen; en je kunt rijen niet weghalen als er een verwijzing naartoe is. Die bescherming is een belangrijke eigenschap van relationele databases.


# Databases ontwerpen

Een database is gemaakt door mensen en voor mensen (en voor machines... die werken voor mensen). Dus een database
moet worden ontworpen. In deze sectie leer je hoe we komen tot een 'zinnig' database ontwerp. Een database die werkt,
zowel voor de beperkingen van een relationeel database systeem, als voor het uitdrukken van de beperkingen van de 'echte' wereld.


## Hoe gaan we te werk

Om een computersysteem, zoals een database, te maken zodat het gebruikt kan worden, hebben we meestal ongeveer deze stappen:

1. Analyse: wat moet er in de database
    - Vragen stellen aan de opdrachtgevers
    - Uitwerkingen maken in diagrammen en terugkoppelen
    - Soms zelfs een proof-of-concept maken

2. Ontwerpen
    - Technisch uitwerken wat alle details zijn van het systeem
    - Bij problemen (iets in de analyse is onmogelijk in techniek), terug naar stap 1

3. Realisatie
    - Het uitwerken van het ontwerp tot een echt systeem
    - Het ergens plaatsen van het systeem zodat het bereikbaar is (hosting)

4. Demonstreren
    - Demo's geven van dit systeem en de klant laten testen

5. Op basis van terugkoppeling bij de demonstratie terug naar stap 2 en het ontwerp bijstellen

En dit proces herhaalt zich tot we een punt bereiken waarop we tevreden zijn voor een eerste live-gang.
De meeste applicaties die we zo maken worden daarna constant bijgewerkt met nieuwe features, en anders op zijn
minst onderhouden.

## Beperkingen van een realtionele database

Zoals we ontdekt hebben bij onze avonturen met SQL, werken relationele databases met tabellen.
In de tabel leggen rijen een 'opname' vast: een weergave van 'iets' in de werkelijkheid. De kolommen van een tabel
zijn de eigenschappen van een opname (of je noemt dat een rij, of in het Engels een record).

Ook weten we van onze lessen met SQL dat er relaties bestaan tussen tabellen. Een kolom in een tabel kan verwijzen
naar een andere tabel. Dit beperkt ons: het is niet mogelijk om direct twee tabellen te koppelen waarbij `docenten` meerdere `vakken` kunnen geven als vakken ook moeten worden gegeven door meerdere docenten.

## Datamodel-ontwerp: terminologie

We zijn nu gewend geraakt aan de termen `tabel`, `kolom` en `rij`. In de database-ontwerp wereld spreken we van:

- *Entiteit*: een 'dinges', een entiteit komt min of meer overeen met een *tabel*
- *Attribuut*: een eigenschap van een entiteit, een attribuut komt min of meer overeen met een *kolom*
- *Type*: een attribuut heeft een type, dat wil zeggen, een beperking in wat voor waarden erin kunnen. Bij onze SQL lessen hebben we gezien dat kolommen een type hebben: getal, tekst, datum; en zo zijn er meer.

Het begrip 'rij' komt niet terug in het ontwerp: de rijen zijn er pas in het gebruik!

## Datamodel-ontwerp: oefeningen

In de lessen bespreek ik wat oefeningen die we doen om tot een database ontwerp
te komen. Gegeven wat tekst of simpelweg een denkbeeldige omgeving: wat zouden
de entiteiten zijn en wat zijn de eigenschappen van zulke entiteiten.


### Voorbeeld uit de les: NS

Jullie docent, Merijn, heeft een paar keer opdrachten bij de NS, de Nederlandse Spoorwegen, gehad.
Wat zouden `entiteiten` kunnen zijn in de wereld van de NS? 

Antwoorden die zoal voorbij komen zijn:

- trein
- station
- kaartje
- ov-chipkaart
- paaltjes / poortjes

Een aardig verhaal bij de NS is dat ze in hun IT-systemen proberen het woord 'trein' te vermijden. Het kan veel verschillende dingen betekenen! 

- een fysiek apparaat dat op rails rijdt,
- een gepland vertrek van station Utrecht, spoor 12, om 17:32 uur in de richting van Amsterdam,
- een goederentrein (die de passagiers dienstverlening dreigt te verstoren)

Een fysieke trein wordt ook wel 'materieel' genoemd; en dan is er nog 'personeel' nodig, machinisten, conducteurs.
En zelfs de term 'bak-samenstellingseenheid' of zoiets is wel ergens gespot; een fysieke trein die uit delen kan bestaan:
je ziet in de trein een 'treinnummer'. Zo'n nummer is zonder twijfel een attribuut van een entiteit in een database!


### Voorbeeld uit de les: een winkel

Webshops zijn er te over. Bedenk entiteiten waar je aan denkt bij een webshop.

tip: Doe dit eerst zonder er een te bekijken. Daarna bekijk er eens een; komen er meer naar boven?

## Database ontwerp, relaties

Een relationele database draait om de relaties die _entiteiten_ met elkaar kunnen hebben:

- _klant_ koopt _product_ 
- _auto_ wordt onderhouden door een _monteur_
- _docent_ doceert een of meer _vakken_


We willen in een ontwerp deze relaties zo precies mogelijk vastleggen.

> Een relatie werkt twee kanten op, dat werkt ook zo bij entiteiten in een database-ontwerp

### Nul, een, meer? 'kardinaliteit'

Voor een database-ontwerp is het van belang te weten 'hoeveel' van de ene entiteit hoort bij de andere entiteit.
Bij de analyse stellen we vragen, zoals: "Klopt het dat een klant meerdere producten in een winkelmandje kan leggen?"
en "Klopt het dat een winkelmandje bij precies 1 klant hoort?".

>Dit lijken eenvoudige vragen; dit klopt voor zo'n beetje elke online winkel! Soms weten we het antwoord niet meteen zoals de vraag: Klopt het dat een patient maximaal 1 infuuspomp tegelijk gebruikt? (Nee, soms zijn er meer medicijnen die onafhankelijk worden toegediend...)

Om deze aantallen vast te leggen zijn er in een database ontwerp precies vier mogelijkheden voor de relaties:

- Nul of 1
- Precies 1
- Nul of meer
- Een of meer


Voorbeelden:

- Van een klant weten we nul of 1 e-mailadres
- Elke regel in een bestelling hoort bij precies 1 bestelling
- Een product wordt gekocht door nul of meer klanten
- Elke bestelling omvat een of meer producten

*Maar* dit is maar de helft van het verhaal! Van al deze zaken willen we ook de andere kant van de relatie weten. Bijvoorbeeld:

- Elke bestelling bestaat uit 1 of meer regels, en
- Klanten kopen een of meer product.

#### ERDish-zinnen

We willen ervoor zorgen dat we structureel alle relaties in de database goed beschrijven.
Dit doen we door relaties tussen entiteiten te beschrijven in een precieze structuur. Voorbeelden:

- _auto_ en _monteur_:
    - *Iedere* _auto_ wordt onderhouden door **precies een** _monteur_.
    - *Iedere* _monteur_ onderhoudt **een of meer** _auto_s.

- _product_ en _klant_
    - *Ieder* _product_ wordt gekocht door **nul of meer** _klanten_.
    - *Iedere* _klant_ koopt **een of meer** _producten_.

Aan de voorbeelden kun je zien dat die zinnen altijd dezelfde structuur hebben:

_Iedere_ **entiteit A** __werkwoord__ ..aantal.. **entiteit B**


En dat de zinnen altijd in paren voorkomen. Als er een relatie is tussen twee entiteiten, dan moet je beide kanten van de relatie beschrijven.

#### Voorbeelden van ERD-ish zin-paren:

- Een leerling volgt meerdere vakken. Vakken worden gevolgd door meerdere leerlingen.
- Elke medewerker werkt voor precies 1 afdeling. Voor iedere afdeling werken een of meer medewerkers.
- Elke klant plaatst nul of meer bestellingen. Iedere bestelling is voor precies een klant.
- Elke gebruiker heeft een of meer accounts. Elk account hoort bij precies 1 gebruiker.


### Entiteit-relatie-diagrammen, een plaatje zegt meer

De 'kardinaliteit' die we hierboven beschreven met woorden als 'precies 1', '1 of meer' tekenen we we als zogenaamde kraaienpoten (de Engelse term
hiervoor is Crows Feet). Dit is een veelgebruikte manier om in een diagram de hoeveelheid (ariteit of kartinaliteit) van een relatie te beschrijven.

Deze kraaienpoten zien er zo uit:


![Plaatje van de vier kraaienpoten](images/crows-feet-enumeration.png)

Een rondje of streep voor de nul of een. Een enkele streep of drie streepjes in de vorm van een 
vogelpootje voor de 'meer'-variant.


### Van ERDish zinnen naar een ERD

We hebben ERDish zinnen gemaakt om de relaties tussen entiteiten te beschrijven. Dit zetten
we om in een diagram op de volgende manier.

- _auto_ en _monteur_:
    - *Iedere* _auto_ wordt onderhouden door **precies een** _monteur_.
    - *Iedere* _monteur_ onderhoudt **meer dan een** _auto_.

![Plaatje van auto monteur ERD](images/erd-voorbeeld-auto-monteur.png)

In dit plaatje:
- Wordt iedere entiteit getoond als rechthoek met afgeronde hoeken.
- Zijn attributen opgenomen
- Staan kraaienpoten
- Staat de betekenis van de relatie beschreven op de lijn


Als er meer entiteiten zijn, dan worden die allemaal ondergebracht in een grote plaat.
In de volgende sectie zien we daarvan een voorbeeld.


## meer-meer: werkt in een ERD maar _niet_ in een relationele database

Soms ontstaat er in een ERD een zogenaamde meer-meer relatie. Dat betekent dat
in de ERDish zinnen, in beide richtingen de relatie 'meer' bevat.

Bijvoorbeeld de relatie tussen klanten en producten:


- _product_ en _klant_
    - *Ieder* _product_ wordt gekocht door **nul of meer** _klanten_.
    - *Iedere* _klant_ koopt **een of meer** _producten_.

Hier hoort in eerste instantie het volgende ERD bij:

![Plaatje van klant bestelt product](images/erd-voorbeeld-klant-product-meer-meer.png)


Als we dit zouden willen opslaan in twee tabellen dan lukt dat niet goed: als we in de klant
een product-kolom zouden opnemen, dan kan de klant maar 1 product bestellen. En als we bij product
een klant zouden willen opnemen, dan kan maar 1 klant dat product bestellen.

Met product bedoelen we bijvoorbeeld 'een zwart T-shirt in maar M', waarvan de winkel er bijvoorbeeld
honderd heeft liggen.

Een oplossing zou kunnen zijn dat we voor elk individueel ding een rij aanmaken in de database, maar
dat voelt raar; we gaan dan heel vaak hetzelfde zeggen in de database-tabel alleen maar om dit probleem op te lossen.

Vaak betekent een meer-meer relatie eigenlijk iets op zichzelf en kunnen we een tabel `bestelling` erbij maken. Die kan dan verwijzen naar `klant` en `product`. Nog handiger is het om een vierde entiteit erbij
te maken, die van de 'bestelregel': wat als ik vier zwarte T-shirts wil bestellen?

De "klassieke" structuur voor klanten die producten kopen wordt dan als volgt:

![Plaatje van klant die bestellingen kan plaatsen](images/erd-voorbeeld-klant-product-meer-meer.png)

Op deze manier heeft is er geen enkele meer-meer relatie. 

> TIP: Maak voor jezelf de ERDish-zinnen bij elke van deze relaties (dus, zes ERDish zinnen).
Klap daarna de sectie hieronder open om je zinnen te controleren.

<details>
  <summary>De ERDish-zinnen voor bovenstaand ERD</summary>
- Iedere _klant_ plaatst *nul of meer* _bestellingen_.
- Iedere _bestelling_ is geplaatst door *precies een* klant.

- Iedere _bestelling_ omvat *een of meer* _bestelregels_.
- Iedere _bestelregel_ zit in *precies een* _bestelling_.

- Iedere _bestelregel_ gaat over *precies een* _product_.
- Ieder _product_ zit in *nul of meer* _bestelregels_.
</details>


# Eindopdracht 1: SQL

Veel meer uitleg over SQL en de eerste inleveropdracht vind je op de website: [Sjaaq](https://sql.merijn.xyz)
Dit is door de docent gemaakt. De score is lineair: hoe meer vragen je goed hebt, hoe hoger je deel-cijfer!

# Eindopdracht 2: Een databasemodel ontwerpen


Als eindopdracht ga je een database-ontwerp maken aan de hand van onderstaande casus.


## De casus

Fantasierijke tuintjes! In een door jou gekozen fantasiewereld zijn tuintjes aangelegd. Deze worden onderhouden
door ijverige tuiniers van alle soorten en maten. Ze kweken er magische of anderszins bijzondere planten of groenten; misschien hebben die wel epische of magische eigenschappen!
Wie beheert welk stukje land? Wanneer moet er worden gezaaid, water worden gegeven of geoogst? En komt er een groot feest als de oogst goed was?

- (2 punt) Verzin tenminste vier en maximaal zes entiteiten. Voor elke entiteit bedenk je wat de attributen zijn.
- (6 punten) Beschrijf de relaties tussen de entiteiten in ERDish zinnen.
- (7 punten) Maak een ERD-diagram van deze entiteiten: zorg ervoor dat er geen meer-meer relaties in zitten door koppel-tabellen te maken als dat nodig is.
- (5 punten) Maak voor elke entiteit een voorbeeld-tabel met alle kolommen
- Bonuspunten: maximaal een punt bonus voor originaliteit in de eigenschappen; cyberpunk, fantasy, discworld, ...

Beoordeling: maximaal 20 punten is een 10; minimum is een 1.


## De beoordeling

De beoordeling gebeurt aan de hand van wat jij inlevert, en bestaat uit twee delen:

- (50% van je cijfer) SQL opdracht in het Sjaaq systeem: https://sql.merijn.xyz Sjaaq
- (50% van je cijfer) Database ontwerp opdracht

Je levert in voor de deadline bovenaan deze pagina.

Voor overige zaken rondom eindopdrachten, zie bovenin deze pagina.

# Bug bounty 2025-2026

Je mag Sjaaq proberen te hacken, onder voorwaarden.

Als je het volgende bereikt, krijg je eeuwige roem (en ik verzin nog een
prijs). Eeuwige roem betekent dat ik op deze pagina een hall-of-fame
maak, en daarop meldt wat je hebt gevonden. Je naam mag erbij, hoeft niet.


> Main quest: Als je in Sjaaq queries van een andere student kunt zien of bewerken, of als je de tabellen van de opgaven kunt zien of bewerken, dan heb je Sjaaq gehackt voor de hoofdprijs. 

(Mogelijk komen hier side-quests)

## Let op! Dit is een productie-systeem!

Dit is een systeem dat 'productie' draait, dat wil zeggen dat als je overlast veroorzaakt, je mensen in problemen brengt. Gebruik daarom een beetje je gezonde verstand bij het hacken.

Daarom mag je in de laatste weken van een blok het systeem niet proberen te hacken.

PS: Wil je echt met grof geschut aan de gang en doe je bijvoorbeeld een module over security, neem contact op met de docent (die van security of Merijn Vogel, die Sjaaq heeft gemaakt).

Wellicht kan ik een extra versie voor je klaarzetten, of krijg je gewoon de hele broncode en mag je 'glass-box' security testen!
Let wel, dit is geen capture the flag, er zit niet gegarandeerd een veiligheidslek in. En de maker heeft verrassend veel vertrouwen in de security (en wil toch graag dat Sjaaq gehackt wordt, dan heeft-ie een verhaal voor een java-conferentie!)

## Wat je mag doen als ethisch hacker

Je mag queries uitvoeren via het query-interface, of op andere manieren proberen het backend dingen te laten doen die de maker niet heeft bedoeld.

## Wat je NIET mag doen als ethisch hacker

- Gaat door je experiment het systeem 'down' (het werkt voor niemand meer goed), meldt het dan onmiddelijk.
- Doe geen denial of service-aanvallen. Dus niet onnodig veel queries spammen, hele grote queries of onzin opslaan.
- Ga niet superveel accounts registreren, dat is niet hacken.

## Wat moet je doen als je een hack vindt

De prijs claimen bij de docent! Dat doe je via een direct bericht in teams en eventueel een mailtje.
Je legt uit wat je hebt gedaan en wat je zien, en waarom je denkt dat je daarmee het systeem hebt gehackt.

Je naam kan op de hall of fame komen te staan. En samenwerken is uiteraard toegestaan.


## Hoe Sjaaq werkt

Sjaaq bestaat uit een javascript front-end met een java programma als backend.
Het gebruikt geen 'frameworks', het is zoveel mogelijk native Java. De enige
echte afhankelijkheden zijn een eenvoudige json library (nanojson) en de
postgres database driver zodat JDBC werkt.

De database wordt benaderd via JDBC. Alle databases zijn postgres.

Er is een hoofd-database waar de opgaves in staan en waarin het werk leerlingen in wordt opgeslagen.
Dat is een gescheiden database ten opzichte van de databases waar de queries van studenten op
worden uitgevoerd.

Elke leerling heeft een eigen database. Dat is een kopie van een template database. Als een leerling zich registreert wordt die database gekopieerd.
Ook worden alle rechten zo gezet dat leerlingen niet per ongeluk in elkaars database zouden kunnen werken (ook al zijn ze identiek).

Data wordt nooit blijvend gewijzigd.

