Skip to content

Instantly share code, notes, and snippets.

@OlivierParent
Last active June 16, 2022 10:46
Show Gist options
  • Select an option

  • Save OlivierParent/13da0b380c274244ed84 to your computer and use it in GitHub Desktop.

Select an option

Save OlivierParent/13da0b380c274244ed84 to your computer and use it in GitHub Desktop.

Revisions

  1. OlivierParent revised this gist Dec 10, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Databases.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    Databases
    Databases
    =========
    ©2014 [Olivier Parent](http://www.olivierparent.be/)

  2. OlivierParent revised this gist Nov 24, 2014. 1 changed file with 27 additions and 27 deletions.
    54 changes: 27 additions & 27 deletions Databases.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    Databases
    =========
    ©2014 Olivier Parent
    ©2014 [Olivier Parent](http://www.olivierparent.be/)

    ----------

    @@ -36,7 +36,7 @@ III. SQL voor MySQL Server

    Het net zoals HTML een **declaratieve** taal. Dit wil zeggen dat het beschrijft **wat** er moet gebeuren, niet hoe het moet gebeuren.

    In deze cursus gaan we de populaire opensource databaseserver [MySQL 5.5](http://dev.mysql.com/doc/refman/5.5/en/) van [Oracle](http://www.oracle.com/be/index.html) gebruiken. Er is ook een opensource kloon van de hand van de oorspronkelijke maker van MySQL: [MariaDB](https://mariadb.org/).
    In deze cursus gaan we de populaire opensource databaseserver [MySQL 5.6](http://dev.mysql.com/doc/refman/5.6/en/) van [Oracle](http://www.oracle.com/be/index.html) gebruiken. Er is ook een opensource kloon van de hand van de oorspronkelijke maker van MySQL: [MariaDB](https://mariadb.org/).

    > **Weetjes:** *My* en *Maria* zijn de twee dochters van Michael Widenius. Vandaar de namen MySQL en MariaDB. Widenius is de medeoprichter van [MySQL AB](http://www.mysql.com/) de Fins-Zweedse firma achter MySQL. De firma werd overgenomen door Sun Microsystems die later op zijn beurt door Oracle werd overgenomen. Uit onvrede hierover creëerde Widenius het opensource alternatief MariaDB.
    @@ -161,7 +161,7 @@ IV. MySQL Server gebruiken

    #### 1.1 Aanmelden

    Aanmelden op de MySQL Server vanaf de *Command-Line Interface* doe je met de [MySQL Command-Line Tool](http://dev.mysql.com/doc/refman/5.5/en/mysql.html) `mysql`.
    Aanmelden op de MySQL Server vanaf de *Command-Line Interface* doe je met de [MySQL Command-Line Tool](http://dev.mysql.com/doc/refman/5.6/en/mysql.html) `mysql`.

    Hulp over het gebruik vraag je met de optie `--help` of `-?`:

    @@ -323,8 +323,8 @@ Bijvoorbeeld:

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / SHOW PRIVILEGES Syntax](http://dev.mysql.com/doc/refman/5.5/en/show-privileges.html)
    > * [MySQL / MySQL 5.5 Reference Manual / SHOW GRANTS Syntax](http://dev.mysql.com/doc/refman/5.5/en/show-grants.html)
    > * [MySQL / MySQL 5.6 Reference Manual / SHOW PRIVILEGES Syntax](http://dev.mysql.com/doc/refman/5.6/en/show-privileges.html)
    > * [MySQL / MySQL 5.6 Reference Manual / SHOW GRANTS Syntax](http://dev.mysql.com/doc/refman/5.6/en/show-grants.html)
    Een databasegebruiker heeft een aantal **Rechten** *(Privileges)* om dingen te doen met of in een database. Je kan een lijst alle **mogelijke rechten** die de server ondersteunt opvragen met:

    @@ -350,7 +350,7 @@ Bijvoorbeeld:

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / GRANT Syntax](http://dev.mysql.com/doc/refman/5.5/en/grant.html)
    > * [MySQL / MySQL 5.6 Reference Manual / GRANT Syntax](http://dev.mysql.com/doc/refman/5.6/en/grant.html)
    Een databasegebruiker alle rechten (`ALL PRIVILEGES`) op alle tabellen (`*`) van een bepaalde database geven (`GRANT``TO`):

    @@ -401,7 +401,7 @@ Rechten kunnen ook meer specifiek toegekend worden. Bijvoorbeeld:
    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / REVOKE Syntax](http://dev.mysql.com/doc/refman/5.5/en/revoke.html)
    > * [MySQL / MySQL 5.6 Reference Manual / REVOKE Syntax](http://dev.mysql.com/doc/refman/5.6/en/revoke.html)
    Een databasegebruiker alle rechten (`ALL PRIVILEGES`) op alle tabellen (`*`) van een bepaalde database ontnemen (`REVOKEFROM`):
    @@ -437,7 +437,7 @@ Bijvoorbeeld:

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / CREATE DATABASE Syntax](http://dev.mysql.com/doc/refman/5.5/en/create-database.html)
    > * [MySQL / MySQL 5.6 Reference Manual / CREATE DATABASE Syntax](http://dev.mysql.com/doc/refman/5.6/en/create-database.html)
    Een database aanmaken doe je met een `CREATE`-statement

    @@ -493,7 +493,7 @@ Dit wil zeggen:

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / USE Syntax](http://dev.mysql.com/doc/refman/5.5/en/use.html)
    > * [MySQL / MySQL 5.6 Reference Manual / USE Syntax](http://dev.mysql.com/doc/refman/5.6/en/use.html)

    Met `USE` geef je aan op welke database de SQL-statements van toepassing zijn. Dit blijft zo voor de rest van de sessie.
    @@ -511,7 +511,7 @@ Bijvoorbeeld:

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / DROP DATABASE Syntax](http://dev.mysql.com/doc/refman/5.5/en/drop-database.html)
    > * [MySQL / MySQL 5.6 Reference Manual / DROP DATABASE Syntax](http://dev.mysql.com/doc/refman/5.6/en/drop-database.html)
    Een database verwijderen doe je met een `DROP`-statement

    @@ -529,7 +529,7 @@ Bijvoorbeeld:

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / mysqldump — A Database Backup Program](http://dev.mysql.com/doc/refman/5.5/en/mysqldump.html)
    > * [MySQL / MySQL 5.6 Reference Manual / mysqldump — A Database Backup Program](http://dev.mysql.com/doc/refman/5.6/en/mysqldump.html)
    Een backup maken van een database kan met het programma `mysqldump`. Je gebruikt dezelfde credentials als voor `mysql` (bijv. databasegebruiker `homestead` met als wachtwoord `secret`).

    @@ -590,7 +590,7 @@ Een gecomprimeerd dumpbestand terugzetten door het te decomprimeren met `gunzip`

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / mysqlimport — A Data Import Program](http://dev.mysql.com/doc/refman/5.5/en/mysqlimport.html)
    > * [MySQL / MySQL 5.6 Reference Manual / mysqlimport — A Data Import Program](http://dev.mysql.com/doc/refman/5.6/en/mysqlimport.html)
    ### 4. Tabellen

    @@ -615,7 +615,7 @@ Bijvoorbeeld:

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / CREATE TABLE Syntax](http://dev.mysql.com/doc/refman/5.5/en/create-table.html)
    > * [MySQL / MySQL 5.6 Reference Manual / CREATE TABLE Syntax](http://dev.mysql.com/doc/refman/5.6/en/create-table.html)
    ```sql
    -- Tabel met kolommen maken
    @@ -651,7 +651,7 @@ Bijvoorbeeld:
    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / EXPLAIN Syntax](http://dev.mysql.com/doc/refman/5.5/en/explain.html)
    > * [MySQL / MySQL 5.6 Reference Manual / EXPLAIN Syntax](http://dev.mysql.com/doc/refman/5.6/en/explain.html)
    `EXPLAIN` (of `DESCRIBE`) is een *Utility Statement* waarmee de eigenschappen van de kolommen omschreven worden:
    @@ -674,7 +674,7 @@ Bijvoorbeeld:

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / ALTER TABLE Syntax](http://dev.mysql.com/doc/refman/5.5/en/alter-table.html)
    > * [MySQL / MySQL 5.6 Reference Manual / ALTER TABLE Syntax](http://dev.mysql.com/doc/refman/5.6/en/alter-table.html)
    Met `ALTER TABLE` kan je een bestaande tabel wijzigen.

    @@ -872,7 +872,7 @@ ALTER TABLE users

    > Zie ook:
    >
    > * [MySQL / MySQL 5.5 Reference Manual / TRUNCATE TABLE Syntax](http://dev.mysql.com/doc/refman/5.5/en/truncate-table.html)
    > * [MySQL / MySQL 5.6 Reference Manual / TRUNCATE TABLE Syntax](http://dev.mysql.com/doc/refman/5.6/en/truncate-table.html)
    Met `TRUNCATE TABLE` kan je een tabel leegmaken. In feite is dit hetzelfde als de tabel verwijderen en daarna opnieuw aanmaken (*to truncate* betekent afknotten).

    @@ -931,7 +931,7 @@ De vier basisbewerkingen die je op rijen kan uitvoeren zijn **CRUD**:

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / INSERT Syntax](http://dev.mysql.com/doc/refman/5.5/en/insert.html)
    > * [MySQL / MySQL 5.6 Reference Manual / INSERT Syntax](http://dev.mysql.com/doc/refman/5.6/en/insert.html)

    Om waardes van het type string toe te voegen gebruikt men enkele aanhalingstekens (`'`).
    @@ -993,7 +993,7 @@ Bijvoorbeeld:

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / SELECT Syntax](http://dev.mysql.com/doc/refman/5.5/en/select.html)
    > * [MySQL / MySQL 5.6 Reference Manual / SELECT Syntax](http://dev.mysql.com/doc/refman/5.6/en/select.html)
    ##### 5.2.1 Rijen Selecteren

    @@ -1379,7 +1379,7 @@ ORDER BY name DESC;

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / UPDATE Syntax](http://dev.mysql.com/doc/refman/5.5/en/update.html)
    > * [MySQL / MySQL 5.6 Reference Manual / UPDATE Syntax](http://dev.mysql.com/doc/refman/5.6/en/update.html)
    * `UPDATE`
    * Expressies in `SET` en `WHERE`
    @@ -1407,7 +1407,7 @@ Bijvoorbeeld:

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / DELETE Syntax](http://dev.mysql.com/doc/refman/5.5/en/delete.html)
    > * [MySQL / MySQL 5.6 Reference Manual / DELETE Syntax](http://dev.mysql.com/doc/refman/5.6/en/delete.html)
    ```sql
    DELETE FROM {tabel}
    @@ -1534,7 +1534,7 @@ Probeer een datatype te kiezen dat zo goed mogelijk past bij het soort gegevens:
    ##### 1.1.1 Integers

    ###### A. Gehele getallen
    [Gehele getallen](http://dev.mysql.com/doc/refman/5.5/en/integer-types.html) *(Integers)* stellen een exacte waarde voor.
    [Gehele getallen](http://dev.mysql.com/doc/refman/5.6/en/integer-types.html) *(Integers)* stellen een exacte waarde voor.

    De integerdatatypes van klein naar groot:

    @@ -1587,7 +1587,7 @@ TINYINT(1)


    ##### 1.1.2 Floating-point
    [Zwevendekommagetallen](http://dev.mysql.com/doc/refman/5.5/en/floating-point-types.html) *(floating-point values)* hebben een waarde bij benadering.
    [Zwevendekommagetallen](http://dev.mysql.com/doc/refman/5.6/en/floating-point-types.html) *(floating-point values)* hebben een waarde bij benadering.

    `FLOAT({p})`

    @@ -1619,7 +1619,7 @@ FLOAT({p})

    ##### 1.1.3 Decimal values

    [Vastekommagetallen](http://dev.mysql.com/doc/refman/5.5/en/precision-math-decimal-characteristics.html) *(Decimal values)* Hebben een exacte waarde.
    [Vastekommagetallen](http://dev.mysql.com/doc/refman/5.6/en/precision-math-decimal-characteristics.html) *(Decimal values)* Hebben een exacte waarde.

    > **Tip:** Gebruik vastekommagetallen voor valuta, want bij geldtransacties mogen geen afrondingsfouten ontstaan.
    @@ -1642,7 +1642,7 @@ DECIMAL({m},{d})

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / String Types](http://dev.mysql.com/doc/refman/5.5/en/string-types.html)
    > * [MySQL / MySQL 5.6 Reference Manual / String Types](http://dev.mysql.com/doc/refman/5.6/en/string-types.html)
    ##### 1.2.1 Tekenstrings

    @@ -1757,7 +1757,7 @@ SQL-92 was de derde revisie en meteen ook een grote. Deze standaard uit 1992 wor

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / String Comparison Functions](http://dev.mysql.com/doc/refman/5.5/en/string-comparison-functions.html)
    > * [MySQL / MySQL 5.6 Reference Manual / String Comparison Functions](http://dev.mysql.com/doc/refman/5.6/en/string-comparison-functions.html)
    Eenvoudige patroonherkenning gebeurt met `LIKE` of `NOT LIKE`.

    @@ -1787,7 +1787,7 @@ Bijvoorbeeld:

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / Regular Expressions](http://dev.mysql.com/doc/refman/5.5/en/regexp.html)
    > * [MySQL / MySQL 5.6 Reference Manual / Regular Expressions](http://dev.mysql.com/doc/refman/5.6/en/regexp.html)
    Patroonherkenning met reguliere expressies gebeurt met `REGEXP` of `NOT REGEXP`.

    @@ -1816,7 +1816,7 @@ Bijvoorbeeld:

    > Zie ook:
    >
    > * [MySQL / MySQL 5.5 Reference Manual / Logical Operators](http://dev.mysql.com/doc/refman/5.5/en/logical-operators.html)
    > * [MySQL / MySQL 5.6 Reference Manual / Logical Operators](http://dev.mysql.com/doc/refman/5.6/en/logical-operators.html)
    Logische operatoren hebben als resultaat **WAAR** (`1` of `TRUE`), **ONWAAR** (`0` of `FALSE`) of **nullwaarde** (`NULL`) en worden van **links naar rechts** geëvalueerd.

  3. OlivierParent revised this gist Nov 11, 2014. 1 changed file with 5 additions and 5 deletions.
    10 changes: 5 additions & 5 deletions Databases.md
    Original file line number Diff line number Diff line change
    @@ -44,12 +44,12 @@ In deze cursus gaan we de populaire opensource databaseserver [MySQL 5.5](http:/

    #### 1.1. Ontstaan van SQL

    Begin jaren 70 ontwikkelde [IBM](http://www.ibm.com/) de taal onder de naam **Sequel**. Vandaar dat veel ontwikkelaars SQL nog altijd uitspreken als "sequel". De **officiële uitspraak** is echter “Es-Qu-El” (/ɛsk'juːˈɛl /).
    Begin jaren 70 ontwikkelde [IBM](http://www.ibm.com/) de taal onder de naam **Sequel**. Vandaar dat veel ontwikkelaars SQL nog altijd uitspreken als "Sequel". De **officiële uitspraak** is echter “Es-Ku-El” `(/ɛsk'juːˈɛl /)`.

    De uitspraak verschilt ook volgens softwareleverancier:
    De uitspraak van de afkorting "SQL" verschilt ook volgens softwareleverancier:

    - Oracle MySQL → My-“Es-Qu-El”
    - Microsoft SQL Server → Microsoft “Sequel” Server
    - Oracle MySQL → My-“Es-Ku-El”
    - Microsoft SQL Server → Microsoft “Sie-kwel” Server

    #### 1.2. SQL-standaard

    @@ -82,7 +82,7 @@ Met SQL-statements kunnen de **vier bewerkingen** op databasegegevens uitgevoerd
    | **Create** | aanmaken/invoeren |
    | **Read** | uitlezen |
    | **Update** | wijzigen |
    | **Delete** (**Drop**) | verwijderen |
    | **Delete**/**Drop** | verwijderen |

    #### 2.2. SQL-subtalen

  4. OlivierParent created this gist Nov 11, 2014.
    2,056 changes: 2,056 additions & 0 deletions Databases.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,2056 @@
    Databases
    =========
    ©2014 Olivier Parent

    ----------

    [TOC]

    ----------

    I. Databaseontwerp
    ------------------


    II. Ontwikkelomgeving
    ---------------------

    In de voorbeelden wordt de ontwikkelomgeving [AHS Laravel Homestead](https://bitbucket.org/olivierparent/homestead) gebruikt.

    De beschikbare DBMS'en in deze ontwikkelomgeving zijn:

    - [MySQL](http://www.mysql.com/)
    - [PostgreSQL](http://www.postgresql.org/)
    - [SQLite](http://www.sqlite.org/)

    Het is ook mogelijk om extra DBMS'en te installeren zoals [MongoDB](http://www.mongodb.org/).

    In de meeste voorbeelden wordt MySQL gebruikt.

    > **Tip:** Mocht je wijzigingen moeten aanbrengen aan de standaardinstallatie, dan vind je in [Handleiding Ubuntu-server](https://help.ubuntu.com/14.04/serverguide/index.html) een hoofdstuk over de [installatie en configuratie van MySQL](https://help.ubuntu.com/14.04/serverguide/mysql.html).
    III. SQL voor MySQL Server
    --------------------------

    ***Structured Query Language*** is een gestandaardiseerde taal om gegevens te beheren in een (relationele) database.

    Het net zoals HTML een **declaratieve** taal. Dit wil zeggen dat het beschrijft **wat** er moet gebeuren, niet hoe het moet gebeuren.

    In deze cursus gaan we de populaire opensource databaseserver [MySQL 5.5](http://dev.mysql.com/doc/refman/5.5/en/) van [Oracle](http://www.oracle.com/be/index.html) gebruiken. Er is ook een opensource kloon van de hand van de oorspronkelijke maker van MySQL: [MariaDB](https://mariadb.org/).

    > **Weetjes:** *My* en *Maria* zijn de twee dochters van Michael Widenius. Vandaar de namen MySQL en MariaDB. Widenius is de medeoprichter van [MySQL AB](http://www.mysql.com/) de Fins-Zweedse firma achter MySQL. De firma werd overgenomen door Sun Microsystems die later op zijn beurt door Oracle werd overgenomen. Uit onvrede hierover creëerde Widenius het opensource alternatief MariaDB.
    ### 1. Inleiding

    #### 1.1. Ontstaan van SQL

    Begin jaren 70 ontwikkelde [IBM](http://www.ibm.com/) de taal onder de naam **Sequel**. Vandaar dat veel ontwikkelaars SQL nog altijd uitspreken als "sequel". De **officiële uitspraak** is echter “Es-Qu-El” (/ɛsk'juːˈɛl /).

    De uitspraak verschilt ook volgens softwareleverancier:

    - Oracle MySQL → My-“Es-Qu-El”
    - Microsoft SQL Server → Microsoft “Sequel” Server

    #### 1.2. SQL-standaard

    De SQL-standaard is [ISO/IEC 9075](http://www.iso.org/iso/search.htm?qt=iso+9075&sort_by=rel&type=simple&published=on&active_tab=standards) waarvan de meest recente versie dateert van 2011.

    #### 1.3. SQL-dialecten

    Elk **Relationeel Databasemanagementsysteem** (RDBMS) gebruikt zijn eigen SQL-**dialect** dat een beetje afwijkt van de standaard.

    Deze dialecten zijn ontstaan uit **technische** noodzaak, omdat de standaard niet alle **functionaliteiten** van de RDBMS omvat of omgekeerd. Ook de **datatypen** kunnen afwijken van de standaard.

    Zo werkt *Microsoft SQL Server* met een uitbreiding van SQL-standaard: [Transact-SQL](http://msdn.microsoft.com/en-us/library/bb510741.aspx) (of kortweg T-SQL).

    ### 2. Syntaxis

    SQL-code is **niet-hoofdlettergevoelig**, maar sleutelwoorden schrijft men bij voorkeur in **kapitalen**.

    SQL-code heeft een **vrije vorm**. Dit wil zeggen dat regeleinden, extra spaties of tabtekens geen invloed hebben.

    Elke regel SQL-code wordt begrensd door een **puntkomma** (`;`). Dit is bij de meeste RDBMS'en verplicht, maar soms is het niet nodig als er maar één regel per keer uitgevoerd kan worden.

    **Commentaar** begint met twee koppeltekens en een spatie (`-- `), maar niet elk RDBMS laat commentaar toe. Zo laat Microsoft Access laat dit bijvoorbeeld niet toe.

    #### 2.1. CRUD

    Met SQL-statements kunnen de **vier bewerkingen** op databasegegevens uitgevoerd worden:

    | Bewerking | Betekenis |
    |:----------------------|:------------------|
    | **Create** | aanmaken/invoeren |
    | **Read** | uitlezen |
    | **Update** | wijzigen |
    | **Delete** (**Drop**) | verwijderen |

    #### 2.2. SQL-subtalen

    ##### 2.2.1. DDL

    *Data Definition Language* beschrijft de structuur van de database. Wordt gebruikt door de **DBD** *(Database Designer)* en softwareontwerpers.

    > **SQL-sleutelwoorden:**
    >
    > * `ALTER`
    > * `CREATE`
    > * `DROP`
    > * `RENAME`
    > * `TRUNCATE`
    > *
    ##### 2.2.2. DML

    *Data Manipulation Language* bewerkt de gegevens in de database verwerkt. Wordt gebruikt door softwareontwerpers en softwareontwikkelaars.

    > **SQL-sleutelwoorden:**
    >
    > * `INSERT`
    > * `SELECT`
    > * `UPDATE`
    > * `REPLACE`
    > *
    ##### 2.2.3. Speciale statements

    De speciale statements:

    - **Administration Statements**
    - **Utility Statements**: hebben een speciaal nut.

    Deze statements gebruikt je normaal gezien enkel via de *Command-Line Interface* van het DBMS, en nooit bij het programmeren van gewone webapps.

    ###### A. Administration Statements

    Deze statements gebruikt een **DBA** *(Database Administrator)* om het DBMS te beheren (o.a. databasegebruikers en databases aanmaken).

    > **SQL-sleutelwoorden:**
    >
    > * `CREATE USER`
    > * `DROP USER`
    > * `GRANT`
    > * `REVOKE`
    > * `SHOW DATABASES`
    > * `SHOW SCHEMAS`
    > *
    ###### B. Utility Statements

    Deze statements hebben een speciaal nut.

    > **SQL-sleutelwoorden:**
    >
    > * `DESCRIBE`
    > * `EXPLAIN`
    > * `USE`
    > *
    IV. MySQL Server gebruiken
    --------------------------

    > **Afspraken voor codevoorbeelden**
    >
    > * Accolades (`{` en `}`): bevatten een placeholder die door een echte waarde moet worden vervangen.
    > * Rechte haakjes (`[` en `]`): bevatten optionele code.
    > * Haakjes (`<` en `>`): bevatten een toets of teken.
    > * Ellips, beletselteken (``): enzovoort, of: zet hier een operand.
    > * Verticale streep (`|`): scheidt mogelijke sleutelwoorden van elkaar.

    ### 1. MySQL Command-Line Tool

    #### 1.1 Aanmelden

    Aanmelden op de MySQL Server vanaf de *Command-Line Interface* doe je met de [MySQL Command-Line Tool](http://dev.mysql.com/doc/refman/5.5/en/mysql.html) `mysql`.

    Hulp over het gebruik vraag je met de optie `--help` of `-?`:

    vagrant@homestead$ mysql -?

    Je kan de versie van MySQL controleren met:

    vagrant@homestead$ mysql --version

    Laten we bijvoorbeeld aanmelden op de MySQL Server van Laravel Homestead. De databasegebruiker is `homestead` en het wachtwoord is `secret`.

    > **Opmerking:** Je wordt gevraagd om het wachtwoord in te typen, maar de cursor zal niet bewegen. Deze beveiligingsinstelling voorkomt dat de lengte van het wachtwoord zichtbaar is.
    >
    > **OPGELET:** Een `<backspace>` wordt als nieuw teken beschouwd!
    vagrant@homestead$ mysql --user=homestead --password
    password: _
    mysql>

    Je kan ook onmiddellijk inloggen met het wachtwoord.

    vagrant@homestead$ mysql --user=homestead --password=secret

    Er bestaat ook een **verkorte vorm** van de opties:

    vagrant@homestead$ mysql -uhomestead -psecret

    > **OPGELET:** Als je het wachtwoord onmiddellijk invult, zal dit zichtbaar zijn met de shellopdracht `history`. Dit houdt een behoorlijk **veiligheidsrisico** in! Gebruik deze manier daarom **nooit** op een productieserver!
    #### 1.2 Afmelden

    Afmelden doe je met `exit`:

    mysql> exit
    Bye
    vagrant@homestead$ _

    #### 1.3 Shellopdrachten aanroepen

    Je kan met `\!` vanuit de MySQL Command-Line Tool shellopdrachten aanroepen. Om bijvoorbeeld het scherm te wissen met de shellopdracht `clear`:

    mysql> \! clear

    Dit heeft hetzelfde effect als:

    vagrant@homestead$ clear

    ### 2. Databasegebruikers

    #### 2.1 Soorten databasegebruikers

    ##### 2.1.1 Databasebeheerder

    Enkel de **Databasebeheerder**, beter bekend als **DBA** *(Database Administrator)*, wordt verondersteld zich aan te melden de **Credentials** van de **rootgebruiker**. Deze rootgebruiker die meestal `root` als databasegebruikersnaam heeft, heeft alle mogelijke rechten.

    In Laravel Homestead heeft de rootgebruiker deze **Credentials:**

    * Databasegebruikersnaam: `root`
    * Databasewachtwoord: `secret`

    ##### 2.1.2 Developers

    **Developers** mogen in principe enkel databaseaccounts met beperkte(re) rechten gebruiken.

    In Laravel Homestead is dat dan bijvoorbeeld:

    * Databasegebruikersnaam: `homestead`
    * Databasewachtwoord: `secret`

    ##### 2.1.3 Applicaties

    Het is erg aangewezen om per applicatie een aparte databasegebruiker aan te maken die enkel rechten heeft op de door de applicatie gebruikte databases. Zo voorkom je dat een applicatie per ongeluk (of moedwillig na een hack) databases van een andere applicatie kan beschadigen.

    #### 2.2 Databasegebruikers **Oplijsten**

    Alle databasegebruikers staan in de tabel `user` van de database `mysql`. Je kan ze eenvoudig oplijsten met een `SELECT`-statement.

    Bijvoorbeeld:

    mysql> SELECT * FROM `mysql`.`user`;

    > **Opmerking:** De **asterisk** (`*`) betekent alle **kolommen** van de tabel, niet alle rijen!
    Om het overzicht te bewaren kan je enkel bepaalde kolommen laten tonen:

    mysql> SELECT Host, User, Password
    -> FROM `mysql`.`user`;

    #### 2.3 Databasegebruiker **Toevoegen**

    Een databasegebruiker toevoegen:

    ```sql
    -- Databasegebruiker aanmaken
    CREATE USER '{db_gebruikersnaam}'
    IDENTIFIED BY '{db_wachtwoord}';
    ```

    > **OPGELET:** **MySQL** laat **maximaal 16 tekens** toe in de databasegebruikersnaam!
    Bijvoorbeeld:

    mysql> CREATE USER 'Olivier'
    -> IDENTIFIED BY 'GeheimWachtwoord';

    > **Tip:** Je kan aan de databasegebruikersnaam ook een **host** of **IP-adres** toevoegen, zodat de databasegebruiker enkel vanaf die host of dat IP-adres kan aanmelden.
    >
    > Bijvoorbeeld:
    >
    > * `'Olivier'@'%'`
    > * `'Olivier'@'127.0.0.1'`
    > * `'Olivier'@'localhost'`
    >
    > De standaardwaarde is `%` en wil zeggen: om het even welke host of welk IP-adres. Net omdat het de standaardwaarde is, mag `@'%'` weggelaten worden.
    ##### Databasewachtwoorden

    Om wachtwoorden te hashen gebruikt MySQL de functie `PASSWORD()`.

    Bijvoorbeeld:

    mysql> SELECT PASSWORD('GeheimWachtwoord') AS `Password Hashcode`;
    +-------------------------------------------+
    | Password Hashcode |
    +-------------------------------------------+
    | *3D79C803D354D9E2929EEE4F6FE9C151728C2801 |
    +-------------------------------------------+
    1 row in set (0.00 sec)

    > **OPGELET:** De `PASSWORD()`-functie mag enkel gebruikt worden om de wachtwoorden van databasegebruikers te hashen. De toegang tot databaseservers is meestal zo goed beveiligd dat een hacker al fysieke toegang tot de server moet hebben om te kunnen inbreken. Voor bijvoorbeeld de wachtwoorden van websitegebruikers is de functie onvoldoende. Met **Rainbow Tables** (tabellen met hashcodes en de oorspronkelijke tekst) kan een hacker snel en makkelijk het oorspronkelijk wachtwoord achterhalen. Rainbow Tables maken hackers zelf, maar ze zijn ook gratis te vinden op websites zoals https://www.freerainbowtables.com/
    Met onderstaand `SELECT`-statement kan je een overzicht krijgen van alle databasegebruikers, en zien wie als wachtwoord `GeheimWachtwoord` heeft:

    mysql> SELECT Host, User, Password,
    -> Password = PASSWORD('GeheimWachtwoord')
    -> AS `Is het wachtwoord 'GeheimWachtwoord'?`
    -> FROM `mysql`.`user`;

    Je kan de functie `PASSWORD()` gebruiken om het wachtwoord van databasegebruikers te wijzigen met behulp van een `UPDATE`-statement. Bijvoorbeeld:

    mysql> UPDATE `mysql`.`user`
    -> SET Password = PASSWORD('AnderWachtwoord')
    -> WHERE User = 'Olivier';

    #### 2.4 Databasegebruiker **Verwijderen**

    Een databasegebruiker verwijderen doe je met een `DROP USER`-statement.

    ```sql
    -- Databasegebruiker verwijderen
    DROP USER '{db_gebruikersnaam}';
    ```

    Bijvoorbeeld:

    mysql> DROP USER 'Olivier';

    #### 2.5 Rechten **Oplijsten**

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / SHOW PRIVILEGES Syntax](http://dev.mysql.com/doc/refman/5.5/en/show-privileges.html)
    > * [MySQL / MySQL 5.5 Reference Manual / SHOW GRANTS Syntax](http://dev.mysql.com/doc/refman/5.5/en/show-grants.html)
    Een databasegebruiker heeft een aantal **Rechten** *(Privileges)* om dingen te doen met of in een database. Je kan een lijst alle **mogelijke rechten** die de server ondersteunt opvragen met:

    ```sql
    -- Alle mogelijke rechten oplijsten (voor deze databaseserver)
    SHOW PRIVILEGES;
    ```
    Bijvoorbeeld:

    mysql> SHOW PRIVILEGES;

    Om de rechten van een bepaalde databasegebruiker op te vragen:

    ```sql
    -- Alle toegekende rechten voor een databasegebruiker
    SHOW GRANTS FOR '{db_gebruiker}';
    ```
    Bijvoorbeeld:

    mysql> SHOW GRANTS FOR 'Olivier';

    #### 2.6 Rechten **Toekennen**

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / GRANT Syntax](http://dev.mysql.com/doc/refman/5.5/en/grant.html)
    Een databasegebruiker alle rechten (`ALL PRIVILEGES`) op alle tabellen (`*`) van een bepaalde database geven (`GRANT``TO`):

    ```sql
    -- Alle rechten toekennen aan een databasegebruiker
    GRANT ALL PRIVILEGES
    ON `{databasenaam}`.*
    TO '{db_gebruikersnaam}';
    ```

    Het bovenstaande SQL-statement geeft de gebruiker alle rechten behalve `GRANT OPTION` (zelf rechten kunnen geven en ontnemen).

    > **Opmerking:** De **backtick** (`` ` ``) is meestal optioneel tenzij de naam een teken bevat die een speciale betekenis heeft in SQL, zoals bijvoorbeeld een koppelteken (`-`).
    Bijvoorbeeld:

    mysql> GRANT ALL PRIVILEGES
    -> ON `database_arteveldehogeschool_be`.*
    -> TO 'Olivier';

    De database hoeft zelfs niet te bestaan, want de databasegebruiker heeft ook rechten om de database aan te maken.

    > **Tip:** Bij een `GRANT``TO` met `IDENTIFIED BY` zal de databasegebruiker automatisch aangemaakt worden als die niet bestaat.
    >
    > ```sql
    > -- Alle rechten toekennen aan nog niet bestaande databasegebruiker
    > GRANT ALL PRIVILEGES
    > ON `{databasenaam}`.`{tabel}`
    > TO '{db_gebruikersnaam}' IDENTIFIED BY '{db_wachtwoord}';
    > ```
    >
    > Bijvoorbeeld:
    >
    >
    > mysql> GRANT ALL PRIVILEGES
    > -> ON `database_arteveldehogeschool_be`.*
    > -> TO 'Olivier' IDENTIFIED BY 'GeheimWachtwoord';
    >
    > In bovenstaand voorbeeld gelden de rechten op alle tabellen (`*`) van de database.
    Rechten kunnen ook meer specifiek toegekend worden. Bijvoorbeeld:
    mysql> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER
    -> ON `database_arteveldehogeschool_be`.*
    -> TO 'Olivier';
    #### 2.7 Rechten **Ontnemen**
    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / REVOKE Syntax](http://dev.mysql.com/doc/refman/5.5/en/revoke.html)
    Een databasegebruiker alle rechten (`ALL PRIVILEGES`) op alle tabellen (`*`) van een bepaalde database ontnemen (`REVOKEFROM`):
    ```sql
    -- Alle rechten ontnemen van een databasegebruiker
    REVOKE ALL PRIVILEGES
    ON `{databasenaam}`.*
    FROM '{db_gebruikersnaam}';
    ```
    Bijvoorbeeld:

    mysql> REVOKE ALL PRIVILEGES
    -> ON `database_arteveldehogeschool_be`.*
    -> FROM 'Olivier';

    ### 3. Databases en Schema's

    Een **database** is een verzameling van tabellen. Die tabellen kunnen daarenboven ook nog eens gegroepeerd worden in **schema's**.

    > **Opmerking:** **MySQL** maakt geen onderscheid tussen een database en een schema. Daarom zijn de de sleutelwoorden `DATABASE` en `SCHEMA` aliassen. Andere DBMS'en, zoals PostgreSQL, maken wel degelijk een onderscheid tussen de twee!
    #### 3.1 Databases **Tonen**

    ```sql
    -- Databases tonen
    SHOW DATABASES;
    ```
    Bijvoorbeeld:

    mysql> SHOW DATABASES;

    #### 3.2 Database **Aanmaken**

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / CREATE DATABASE Syntax](http://dev.mysql.com/doc/refman/5.5/en/create-database.html)
    Een database aanmaken doe je met een `CREATE`-statement

    ```sql
    -- Database aanmaken
    CREATE DATABASE `{databasenaam}`;
    ```
    > **Tip:** Voorkom foutmeldingen door **voorwaardelijke statements** te gebruiken. Hiervoor gebruik je `IF EXISTS` of `IF NOT EXISTS`
    >
    > Bijvoorbeeld:
    >
    > mysql> CREATE DATABASE IF NOT EXISTS `database_arteveldehogeschool_be`;
    In **MySQL** kan je exact hetzelfde bereiken met `SCHEMA` omdat dit een alias is voor `DATABASE`:

    ```sql
    -- Schema aanmaken
    CREATE SCHEMA [IF NOT EXISTS] `{schemanaam}`;
    ```

    Je kan ook een standaard **tekencodering** (`CHARACTER SET`) en **sorteervolgorde** (`COLLATE`) instellen.

    ```sql
    -- Database aanmaken
    CREATE DATABASE [IF NOT EXISTS] `{databasenaam}`
    DEFAULT CHARACTER SET {tekencodering}
    COLLATE {sorteervolgorde};
    ```

    > **Opmerking:** De **collatie** *(collation)* is de **sorteervolgorde** van de tekens. In bepaalde talen is dit heel belangrijk. Zo wordt bijvoorbeeld de Duitse letter 'Ä' als gewone 'A' aanzien bij het sorteren, terwijl de Zweedse letter 'Å' na de 'Z' komt in het alfabet. Bij een sorteervolgorde die **hoofdlettergevoelig** is komt bovenkast voor onderkast. Dus eerst 'A' tot en met 'Z' en dan pas 'a' tot en met 'z'.
    Bijvoorbeeld:

    mysql> CREATE DATABASE IF NOT EXISTS `database_arteveldehogeschool_be`
    -> DEFAULT CHARACTER SET utf8
    -> COLLATE utf8_general_ci;

    Dit wil zeggen:

    * `IF NOT EXISTS`: Het create statement wordt enkel uitgevoerd als er nog geen database is met deze naam.
    * `CHARACTER SET utf8`: De standaardtekencodering van de tabellen is [UTF-8](http://tools.ietf.org/html/rfc3629) *(8-bit Unicode Transformation Format)*.
    * `COLLATE utf8_general_ci` wil zeggen dat de sorteervolgorde gebeurt volgens:
    * `utf8`: UTF-8-tekencodering
    * `general`: algemeen (niet-taalspecifiek)
    * `ci`: niet-hooflettergevoelig *(case insensitive)*


    > **Tip:** Je can het `CREATE DATABASE`-statement van een bestaande database opvragen met:
    >
    > SHOW CREATE DATABASE `{databasenaam}`
    #### 3.3 Database **Selecteren** voor Gebruik

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / USE Syntax](http://dev.mysql.com/doc/refman/5.5/en/use.html)

    Met `USE` geef je aan op welke database de SQL-statements van toepassing zijn. Dit blijft zo voor de rest van de sessie.

    ```sql
    -- Database (of schema) als standaard instellen
    USE `{databasenaam}`;
    ```

    Bijvoorbeeld:

    mysql> USE `database_arteveldehogeschool_be`;

    #### 3.4 Database **Verwijderen**

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / DROP DATABASE Syntax](http://dev.mysql.com/doc/refman/5.5/en/drop-database.html)
    Een database verwijderen doe je met een `DROP`-statement

    ```sql
    -- Database verwijderen
    DROP DATABASE [IF EXISTS] `{databasenaam}`;
    ```
    Bijvoorbeeld:

    mysql> DROP DATABASE IF EXISTS `database_arteveldehogeschool_be`;

    #### 3.5 Database **Back-uppen**

    ##### 3.5.1 Back-up **Maken**

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / mysqldump — A Database Backup Program](http://dev.mysql.com/doc/refman/5.5/en/mysqldump.html)
    Een backup maken van een database kan met het programma `mysqldump`. Je gebruikt dezelfde credentials als voor `mysql` (bijv. databasegebruiker `homestead` met als wachtwoord `secret`).

    Hulp over het gebruik vraag je met de optie `--help` of `-?`:

    vagrant@homestead$ mysqldump -?

    Je kan de SQL-statements naar het scherm laten dumpen. Bijvoorbeeld:

    vagrant@homestead$ mysqldump -uhomestead -p database_arteveldehogeschool_be
    Enter password: _

    Je kan de dump ook omleiden naar een bestand door de *redirect output to file*-operator (`>`) van de shell te gebruiken. Bijvoorbeeld:

    vagrant@homestead$ mysqldump -uhomestead -p database_arteveldehogeschool_be > ~/Code/dump.sql
    Enter password: _


    Als je een historiek wil bijhouden kan je de dumps ook een **timestamp** geven met `$(date +"%Y-%m-%d_%H%M%S")`. Bijvoorbeeld:

    vagrant@homestead$ mysqldump -uhomestead -p database_arteveldehogeschool_be > ~/Code/dump_$(date +"%Y-%m-%d_%H%M%S").sql
    Enter password: _

    Om de `CREATE DATABASE`-statements ook te laten generen moet je de optie `--databases` of `-B` toevoegen. Met deze optie kan je ook **meerdere databases** tegelijk back-uppen door de databasenamen na elkaar op te geven, telkens met een spatie ertussen.

    vagrant@homestead$ mysqldump -uhomestead -p --databases database_arteveldehogeschool_be > ~/Code/dump.sql
    Enter password: _

    Je kan ook **alle databases** laten dumpen, (dus ook die databases die MySQL zelf gebruikt zoals `mysql`, door de optie `--all-databases` of `-A` te gebruiken.

    vagrant@homestead$ mysqldump -uhomestead -p --all-databases > ~/Code/dump.sql
    Enter password: _

    Je kan de dumpbestanden ook **comprimeren** met `gzip` en de optie `-c` *(output to console)*:

    vagrant@homestead$ mysqldump -uhomestead -p --databases database_arteveldehogeschool_be | gzip -c > dump.sql.gz

    ##### 3.5.2 Back-up **Terugzetten**

    De dumpbestanden terugzetten doe je met `mysql`.

    Een dumpbestand **zonder** `DATABASE CREATE`-statement terugzetten:

    vagrant@homestead$ mysql -uhomestead -p database_arteveldehogeschool_be < ~/Code/dump.sql
    Enter password: _

    Een dumpbestand **met** `DATABASE CREATE`-statement terugzetten:

    vagrant@homestead$ mysql -uhomestead -p < ~/Code/dump.sql
    Enter password: _

    Een gecomprimeerd dumpbestand terugzetten door het te decomprimeren met `gunzip` en de optie `-c` *(output to console)*:

    vagrant@homestead$ gunzip -c ~/Code/dump.sql.gz | mysql -uhomestead -p
    Enter password: _

    ##### 3.5.3 Back-up **Importeren**

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / mysqlimport — A Data Import Program](http://dev.mysql.com/doc/refman/5.5/en/mysqlimport.html)
    ### 4. Tabellen

    Een database bevat **Tabellen** *(Tables)*. Elke tabel bestaat uit **Kolommen** *(Columns)* en kan **Rijen** *(Rows)* bevatten. Een rij heeft voor elke kolom een overeenkomstig **Veld** *(Field)* waarin de **Gegevens** *(Data)* opgeslagen worden. De eigenschappen van een veld worden door de kolom bepaald.

    #### 4.1 Tabellen **Tonen**

    Met `SHOW TABLES` kan je alle tabellen in een database of schema opvragen.

    ```sql
    SHOW TABLES;
    ```
    Bijvoorbeeld:

    mysql>USE database_arteveldehogeschool_be;
    mysql>SHOW TABLES;
    Empty set (0.00 sec)

    mysql> _

    #### 4.2 Tabel **Maken**

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / CREATE TABLE Syntax](http://dev.mysql.com/doc/refman/5.5/en/create-table.html)
    ```sql
    -- Tabel met kolommen maken
    CREATE TABLE [IF NOT EXISTS] {tabel} (
    {kolom_1} {DATATYPE}[,
    {kolom_2} {DATATYPE}…]
    );
    ```
    Bijvoorbeeld:

    mysql> CREATE TABLE IF NOT EXISTS `users` (
    -> id INT,
    -> first_name VARCHAR(255),
    -> last_name VARCHAR(255),
    -> username VARCHAR(255),
    -> password CHAR(60),
    -> created_at TIMESTAMP
    -> );

    > **Tip:** Vraag het `CREATE`-statement van de tabel op met `SHOW CREATE TABLE`.
    >
    > Hiermee kan je:
    >
    > * een backup van de structuur maken;
    > * gedetailleerde informatie over de structuur van een tabel te zien.
    >
    > ```sql
    > -- CREATE-statement tonen
    > SHOW CREATE TABLE {tabel};
    > ```
    #### 4.3 Tabel **Omschrijven**
    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / EXPLAIN Syntax](http://dev.mysql.com/doc/refman/5.5/en/explain.html)
    `EXPLAIN` (of `DESCRIBE`) is een *Utility Statement* waarmee de eigenschappen van de kolommen omschreven worden:
    1. Field;
    2. Type;
    3. Null;
    4. Key;
    5. Default;
    6. Extra.
    ```sql
    -- Eigenschappen van de kolommen
    EXPLAIN|DESCRIBE {tabel};
    ```
    Bijvoorbeeld:

    mysql> EXPLAIN users;

    #### 4.4 Tabel **Wijzigen**

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / ALTER TABLE Syntax](http://dev.mysql.com/doc/refman/5.5/en/alter-table.html)
    Met `ALTER TABLE` kan je een bestaande tabel wijzigen.

    ##### 4.4.1 Kolom **Toevoegen**

    - `ADD`
    - Voeg een kolom toe.
    - `COLUMN` is optioneel.


    ```sql
    -- Kolom toevoegen
    ALTER TABLE {tabel}
    ADD [COLUMN] {kolom} {DATATYPE};

    -- Meerdere kolommen toevoegen
    ALTER TABLE {tabel}
    ADD [COLUMN] (
    {kolom_1} {DATATYPE}[,
    {kolom_2} {DATATYPE}…]
    );
    ```

    ##### 4.4.2 Kolom **Wijzigen**

    Met `CHANGE` (of `CHANGE COLUMN`) wijzig je de naam van de kolom. Je moet ook het datatype meegeven, zodat je er bovendien ook het het datatype mee kan wijzigen.

    ```sql
    -- Kolom nieuwe naam geven, en eventueel ook een ander datatype
    ALTER TABLE {tabelnaam}
    CHANGE [COLUMN] {kolomnaam_oud}
    {kolomnaam_nieuw} {DATATYPE};
    ```

    Met `MODIFY` (of `MODIFY COLUMN`) kan je enkel het datatype van de kolom wijzigen.

    ```sql
    -- De kolom een ander datatype geven
    ALTER TABLE {tabelnaam}
    MODIFY [COLUMN] {kolom} {DATATYPE};
    ```

    * `UNSIGNED`
    * Enkel positieve getallen.
    * Verdubbelt de toegelaten maximumwaarde.
    * Gebruik dit bijvoorbeeld samen met de beperkingen `PRIMARY KEY` en `AUTO_INCREMENT`.
    * `SIGNED`
    * Positieve en negatieve getallen.
    * Standaardinstelling, maar kan gebruikt worden om `UNSIGNED` te verwijderen.

    ```sql
    -- Kolom wijzigen naar enkel positieve getallen
    ALTER TABLE {tabelnaam}
    MODIFY [COLUMN] {kolomnaam} {DATATYPE} UNSIGNED;

    -- Kolom terigzetten naar standaardinstelling voor getallen
    ALTER TABLE {tabelnaam}
    MODIFY [COLUMN] {kolomnaam} {DATATYPE} SIGNED;
    ```

    Een kolom kan je een aantal **randvoorwaarden** *(constraints)* opleggen:

    * `PRIMARY KEY`: **PK**, primaire sleutel van de tabel.
    * `NOT NULL`: de waarde moet ingevuld worden.
    * `NULL`: de waarde mag leeggelaten worden.
    * `UNIQUE`: elke rij moet een unieke waarde hebben in deze kolom van de tabel.
    * `AUTO_INCREMENT`: bij elke nieuwe rij wordt de waarde van de **integer** met 1 verhoogd (geïncrementeerd). De kolom is een sleutel. Wordt vaak wordt vaak gebruikt om een **surrogaatsleutel** te maken.

    ```sql
    -- Kolom wijzigen naar PK
    ALTER TABLE {tabelnaam}
    MODIFY [COLUMN] {kolomnaam} {DATATYPE} PRIMARY KEY;

    -- PK verwijderen
    ALTER TABLE {tabelnaam}
    DROP PRIMARY KEY;

    -- Kolom wijzigen naar AUTO_INCREMENT
    ALTER TABLE {tabelnaam}
    MODIFY [COLUMN] {kolomnaam} {DATATYPE} AUTO_INCREMENT;
    ```

    * `NOT NULL`
    * Dit attribuut mag geen null-waarde (ontbrekende waarde) hebben.
    * Verwijder de beperking met `NULL`

    ```sql
    -- Kolom wijzigen zodat er een waarde ingevuld moet worden
    ALTER TABLE {tabelnaam}
    MODIFY [COLUMN] {kolomnaam} {DATATYPE} NOT NULL;

    -- De beperking ongedaan maken
    ALTER TABLE {tabelnaam}
    MODIFY [COLUMN] {kolomnaam} {DATATYPE} NULL;
    ```

    * `UNIQUE`
    * Elke rij moet een unieke waarde hebben in deze kolom van de tabel.

    ```sql
    -- Kolom wijzigen naar unieke waarden
    ALTER TABLE {tabelnaam}
    MODIFY [COLUMN] {kolomnaam} {DATATYPE} UNIQUE;
    ```

    ##### 4.4.3 Standaardwaarde voor een kolom
    Met `DEFAULT` kan je een standaardwaarde voorzien voor een kolom. Telkens een nieuwe rij wordt ingevoegd zonder een waarde op te geven voor die kolom, wordt deze standaardwaarde gebruikt.

    ```sql
    -- Standaardwaarde voor de kolom
    ALTER TABLE {tabel}
    MODIFY [COLUMN] {kolom} {DATATYPE} DEFAULT {waarde};
    ```

    ##### 4.4.4 Commentaar bij een kolom

    Met `COMMENT` kan je commentaar toevoegen aan een kolom. Dit is handig voor DBA's (databasebeheerders) of developers zodat die weten welk soort gegevens in de kolom staan.

    ```sql
    -- Commentaar voor de kolom
    ALTER TABLE {tabel}
    MODIFY [COLUMN] {kolom} {DATATYPE} COMMENT {waarde};
    ```

    Voorgaande wijzigingen kunnen in één statement gecombineerd worden.
    De volgorde is niet van belang.

    ```sql
    -- Kolom wijzigen
    ALTER TABLE {tabel}
    MODIFY {kolom} {DATATYPE} PRIMARY KEY NOT NULL UNSIGNED;
    ```

    ##### 4.4.5 Randvoorwaarden **Opleggen**

    ###### A. Primaire Sleutel *(Primary Key)*

    `CONSTRAINT PRIMARY KEY`

    ```sql
    -- PK toevoegen
    ALTER TABLE {tabel}
    ADD CONSTRAINT PRIMARY KEY ({kolom});

    -- Samengestelde PK toevoegen
    ALTER TABLE {tabel}
    ADD CONSTRAINT PRIMARY KEY ({kolom_1}[, {kolom_2}…]);
    ```

    ###### B. Externe Sleutel *(Foreign Key)*

    * `FOREIGN KEY`
    * Externe Sleutel(s).
    * Hebben een naam.
    * Kunnen verwijderd worden aan de hand van die naam.
    * `REFERENCES`
    * De tabel en de PK waarnaar verwezen wordt.
    * De tabel moet reeds bestaan!


    ```sql
    -- FK toevoegen
    ALTER TABLE {tabel_A}
    ADD CONSTRAINT fk_{tabel_A}_{tabel_B}{0}
    FOREIGN KEY ({kolom_A1})
    REFERENCES {tabel_B} ({kolom_B1});

    -- FK en PK toevoegen
    ALTER TABLE {tabel_A}
    ADD CONSTRAINT PRIMARY KEY ({kolom_A1}),
    ADD CONSTRAINT fk_{tabel_A}_{tabel_B}{0}
    FOREIGN KEY ({kolom_A1})
    REFERENCES {tabel_B} ({kolom_B1});
    ```

    ###### C. Controle

    * `CONSTRAINT CHECK`
    * Expressie waaraan voldaan moet worden.

    > **OPGELET:** Voorlopig in nog geen enkele storage engine van MySQL geïmplementeerd. Gebruik een `TRIGGER` om hetzelfde effect te bereiken.
    ```sql
    -- Controle toevoegen
    ALTER TABLE {tabel}
    ADD CONSTRAINT CHECK ({expressie});

    -- Gebruiker moet minstens 18 jaar zijn
    -- WERKT NIET IN MySQL!
    ALTER TABLE users
    ADD CONSTRAINT CHECK (user_age >= 18);
    ```

    #### 4.5 Tabel **Leegmaken**

    > Zie ook:
    >
    > * [MySQL / MySQL 5.5 Reference Manual / TRUNCATE TABLE Syntax](http://dev.mysql.com/doc/refman/5.5/en/truncate-table.html)
    Met `TRUNCATE TABLE` kan je een tabel leegmaken. In feite is dit hetzelfde als de tabel verwijderen en daarna opnieuw aanmaken (*to truncate* betekent afknotten).

    ```sql
    -- Tabel leegmaken
    TRUNCATE TABLE {tabel};
    ```

    #### 4.6 Tabel **Hernoemen**

    Met `RENAME TABLE` kan je een tabel een nieuwe naam geven.

    ```sql
    -- Tabel nieuwe naam geven
    RENAME TABLE
    {tabelnaam_oud} TO {tabelnaam_nieuw};

    -- Meerdere tabellen een nieuwe naam geven
    RENAME TABLE
    {tabelnaam_A_oud} TO {tabelnaam_A_nieuw}[,
    {tabelnaam_B_oud} TO {tabelnaam_B_nieuw}…];
    ```

    #### 4.7 Kolommen en sleutels verwijderen

    - `DROP COLUMN`: Kolom verwijderen.
    - `DROP PRIMARY KEY`: Primaire Sleutel verwijderen.
    - `DROP FOREIGN KEY`: Externe Sleutel verwijderen.
    - `DROP KEY` Sleutel verwijderen. Na het verwijderen van een Externe Sleutel blijft er nog een gewone Sleutel over.

    ```sql
    -- Kolom verwijderen
    ALTER TABLE {tabel}
    DROP COLUMN {kolom};

    -- PK (Primaire Sleutel) verwijderen
    ALTER TABLE {tabel}
    DROP PRIMARY KEY;

    -- FK (Externe Sleutel) verwijderen
    ALTER TABLE {tabel_A}
    DROP FOREIGN KEY fk_{tabel_A}_{tabel_B}{0},
    DROP KEY fk_{tabel_A}_{tabel_B}{0};
    ```

    ### 5. Rijen

    De vier basisbewerkingen die je op rijen kan uitvoeren zijn **CRUD**:

    * Create
    * Read
    * Update
    * Delete (Drop)

    #### 5.1 Rijen **Toevoegen** [CRUD: Create]

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / INSERT Syntax](http://dev.mysql.com/doc/refman/5.5/en/insert.html)

    Om waardes van het type string toe te voegen gebruikt men enkele aanhalingstekens (`'`).
    De set van waarden staan tussen ronde haakjes.

    ```sql
    -- Rij toevoegen aan tabel
    INSERT INTO {tabel} (
    {kolom_1}[,
    {kolom_2}…]
    )
    VALUES (
    {waarde_1}[,
    {waarde_2}…]
    );
    ```

    Bijvoorbeeld:

    mysql> INSERT INTO addresses (
    -> street,
    -> number
    -> )
    -> VALUES (
    -> 'Industrieweg',
    -> 232
    -> );

    In bovenstaand voorbeeld gaan we ervan uit dat:

    * er een kolom `id` bestaat die de PK is en als datatype `INTEGER AUTO_INCREMENT` heeft, zodat elke nieuwe rij automatisch een veld `id` krijgt met een waarde die 1 hoger is dan die van de vorige rij;
    * `number` een **integer** (geheel getal) is, zodat we de waarde zonder rechte aanhalingstekens schrijven.

    Meerdere rijen toevoegen kan ook.
    De sets van waarden worden door een komma (,) gescheiden

    ```sql
    INSERT [INTO] {tabel} (
    {kolom_1}[,
    {kolom_2}…]
    )
    VALUES (
    {waarde_1a}[,
    {waarde_2a}…]
    )[, (
    {waarde_1b}[,
    {waarde_2b}…]
    )…];
    ```
    Bijvoorbeeld:

    mysql> INSERT INTO addresses
    -> (street, number)
    -> VALUES
    -> ('Industrieweg', 232),
    -> ('Hoogpoort', 15);

    #### 5.2 Rijen **Selecteren** [CRUD: Read]

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / SELECT Syntax](http://dev.mysql.com/doc/refman/5.5/en/select.html)
    ##### 5.2.1 Rijen Selecteren

    De **asterisk** (*) is een jokerteken waarmee je **alle kolommen** selecteert, niet alle rijen!

    Als er uit meerdere tabellen tegelijk geselecteerd wordt, moet de tabelnaam gespecificeerd worden.

    ```sql
    -- Toon de rijen met alle kolommen (*) van de tabel
    SELECT * FROM {tabel};

    --
    SELECT
    {kolom_1}[,
    {kolom_2}…]
    FROM {tabel};

    --
    SELECT
    {tabel}.{kolom_1}[,
    {tabel}.{kolom_2}…]
    FROM {tabel};
    ```

    > **Tip:** Gebruik een **alias** (`AS`) om query's in te korten of beter leesbaar te maken. Een alias kan dan doorheen de query gebruikt worden.
    >
    > Er zijn twee soorten:
    >
    > * kolomalias
    > * tabelalias
    >
    > Voor tabelaliassen is het sleutelwoord `AS` optioneel. Laat het daarom bij voorkeur weg.
    ```sql
    -- Alias voor de tabelnaam
    SELECT
    {tabelalias}.{kolom_1}[,
    {tabelalias}.{kolom_2}…]
    FROM {tabel} [AS] {tabelalias};
    ```

    Bijvoorbeeld:

    mysql> SELECT u.first_name
    -> FROM users AS u;

    of beter en korter:

    mysql> SELECT u.first_name
    -> FROM users u;

    ```sql
    -- Aliassen voor de tabelnaam en de kolomnaam
    SELECT
    {tabelalias}.{kolom_1} AS {kolomalias_1} [,
    {tabelalias}.{kolom_2} AS {kolomalias_2}…]
    FROM {tabel} [AS] {tabelalias};
    ```

    > **Tip:** Gebruik **back ticks** (\`) als de alias een spatie of een gereserveerd teken of woord bevat.
    >
    > mysql> SELECT
    > -> u.first_name AS `De gebruikersnaam`
    > -> FROM users u;
    ##### 5.2.2 Rijen uit het resultaat **Beperken**

    Met het sleutelwoord `LIMIT` kan het aantal rijen uit het queryresultaat beperkt worden.

    Om `{n}` rijen te tonen.
    Met een optionele **offset** kan de selectierij opgegeven worden vanaf waar de `{n}` volgende rijen getoond moeten worden.

    > **OPGELET:** *Microsoft SQL Server* gebruikt hiervoor `TOP`, maar de syntaxis is volledig anders.
    ```sql
    -- {n} rijen tonen
    SELECT {kolom(men)}
    FROM {tabel}
    LIMIT [{offset},]{n};
    ```

    Voorbeeld 1: de 4 eerste rijen tonen uit het queryresultaat.

    mysql> SELECT *
    -> FROM users
    -> LIMIT 4;

    Voorbeeld 2: eerst 5 rijen overslaan uit het queryresultaat en dan de eerste 4 resterende rijen tonen.

    mysql> SELECT *
    -> FROM users
    -> LIMIT 5,4;

    ```sql
    -- Alternatieve manier
    SELECT {kolom(men)}
    FROM {tabel}
    LIMIT {n} [OFFSET {offset}];
    ```

    Voorbeeld 3: eerst 5 rijen overslaan uit het queryresultaat en dan de eerste 4 resterende rijen tonen.

    mysql> SELECT *
    -> FROM users
    -> LIMIT 4 OFFSET 5;

    Standaard worden alle selectierijen getoond, ook selectierijen die er identiek uitzien (hoewel de eigenlijke rij altijd uniek is). Omdat `ALL` de standaard is, wordt dit eigenlijk nooit geschreven.

    Met `DISTINCT` (of `DISTINCTROW`) worden enkel de onderscheiden rijen getoond. De duplicaten worden uit de selectie gefilterd.

    ```sql
    -- Selecteer alle rijen
    SELECT [ALL] {kolom(mem)}
    FROM {tabel};

    -- Filter duplicaten uit de selectie
    SELECT DISTINCT {kolom(mem)}
    FROM {tabel};

    -- Synoniem voor DISTINCT
    SELECT DISTINCTROW {kolom(mem)}
    FROM {tabel};
    ```

    ##### 5.2.3 Uit meerdere tabellen tegelijk selecteren

    Er kan uit meerdere tabellen tegelijk geselecteerd worden.

    ###### A. Combineren

    Hierbij wordt elke rij van de ene tabel met elke rij van de andere tabellen gecombineerd.

    > **OPGELET:** Deze manier van tabellen combineren wordt AFGERADEN!
    ```sql
    -- Selectie uit meerdere tabellen
    SELECT {kolom(mem)}
    FROM tabel_A [, tabel_B…];
    ```

    ###### B. Combineren met `NATURAL JOIN`

    Tabellen kunnen in een selectie gecombineerd worden met een `NATURAL JOIN`. Kolommen met dezelfde kolomnaam in beide tabellen worden samengevoegd. Toont enkel de rijen waarvan de waarde in de gemeenschappelijke kolom overeenkomt.

    ```sql
    -- Selectie uit meerderetabellen
    SELECT {kolom(mem)}
    FROM
    {tabel_A} {tabelalias_A}
    NATURAL JOIN {tabel_B} {tabelalias_B};
    ```

    Met de optionele sleutelwoorden `LEFT` en `RIGHT` wordt de selectie uitgebreid, zodat respectievelijk alle rijen van de linker of alle rijen van de rechter tabel getoond worden.

    ```sql
    -- Alle rijen uit {tabel_A} plus
    -- overeenkomstige rijen uit {tabel_B}
    SELECT *
    FROM {tabel_A} {tabelalias_A}
    NATURAL LEFT JOIN {tabel_B} {tabelalias_B};

    -- Alle rijen uit {tabel_B} plus
    -- overeenkomstige rijen uit {tabel_A}
    SELECT *
    FROM {tabel_A} {tabelalias_A}
    NATURAL RIGHT JOIN {tabel_B} {tabelalias_B};
    ```

    ###### C. Combineren met `INNER JOIN … USING|ON`

    De `INNER JOIN … USING|ON` is een alternatief voor een gewone `NATURAL JOIN`.

    * `LEFT JOIN` is een alternatief voor een `NATURAL LEFT JOIN`.
    * `RIGHT JOIN` is een alternatief voor een `NATURAL RIGHT JOIN`.

    `INNER JOIN … USING `

    Met `USING (…)` geef je de kolomnaam of -namen op waarop de tabellen samengevoegd moeten worden.

    ```sql
    -- INNER JOIN … USING (…)
    SELECT {kolom(mem)}
    FROM {tabel_A} {tabelalias_A}
    INNER JOIN {tabel_B} {tabelalias_B}
    USING ({kolom_1}[, {kolom_2}…]);
    ```

    `INNER JOIN … ON `

    Met `ON …` gebruik je een expressie, bijvoorbeeld:
    `linker_tabel.id = rechter_tabel.id`

    ```sql
    -- INNER JOIN … ON vergelijking
    SELECT {kolom(mem)}
    FROM {tabel_A} {tabelalias_A}
    INNER JOIN {tabel_B} {tabelalias_B}}
    ON {tabelalias_A}.{kolom_A1} = {tabelalias_B}.{kolom_B1};
    ```

    ###### D. Combineren met `LEFT|RIGHT JOIN … USING|ON`

    `LEFT|RIGHT JOIN … USING`
    ```sql
    -- LEFT JOIN … USING (…)
    SELECT {kolom(mem)}
    FROM {tabel_A} {tabelalias_A}
    LEFT|RIGHT JOIN {tabel_B} {tabelalias_B}
    USING ({kolom_1}[, {kolom_2}…]);
    ```

    `LEFT|RIGHT JOIN … ON`

    ```sql
    -- LEFT JOIN … ON vergelijking
    SELECT {kolom(mem)}
    FROM {tabel_A} {tabelalias_A}
    LEFT|RIGHT JOIN {tabel_B} {tabelalias_B}
    ON {tabelalias_A}.{kolom} = {tabelalias_B}.{kolom};
    ```

    ##### 5.2.4 Conditioneel selecteren

    ###### A. De `WHERE`-clausule

    * Werkt met expressies.
    * De evaluatievolgorde hangt af van de gebruikte logische operator
    * Gebruik `(` en `)` om de evaluatievolgorde te bepalen.

    ```sql
    -- selectie van rijen met een
    -- WHERE-clausule
    SELECT {kolom(mem)}
    FROM {tabel}
    WHERE
    {kolom_1} {OPERATOR} {waarde_1}
    [AND|OR|XOR
    {kolom_2} {OPERATOR} {waarde_2}…];
    ```

    ###### B. Patroonherkenning

    `LIKE` werkt met patronen.

    ```sql
    -- Selectie van rijen met een
    -- WHERE-clausule
    SELECT {kolom(mem)}
    FROM {tabel}
    WHERE
    {kolom} [NOT] LIKE {patroon};

    -- Voorbeeld
    -- Selecteer zowel Tim, Timoty,
    -- Tom als Tomas
    SELECT first_name
    FROM users
    WHERE first_name LIKE 'T[io]m%';
    ```

    ###### C. Waarde tussen minimum en maximum

    * `BETWEEN {min} AND {max}`
    * `NOT BETWEEN {min} AND {max}`

    > **OPGELET:** Zowel de minimum- als maximumwaarde zijn inbegrepen in de selectie!
    ```sql
    SELECT {kolom(men)}
    FROM {tabel}
    WHERE
    {kolom} [NOT] BETWEEN {min} AND {max};

    -- Bovenstaande query is de iets kortere versie van dit:
    SELECT {kolom(men)}
    FROM {tabel}
    WHERE
    [NOT] ({min} <= {kolom} AND {kolom} <= {max});
    ```

    ###### D. Waarden in een reeks

    * `IN`: waarde moet in de reeks staan
    * `NOT IN`: waarde mag niet in de reeks staan

    ```sql
    SELECT {kolom(men)}
    FROM {tabel}
    WHERE
    {kolom} [NOT] IN ({waarde_1}[, {waarde_2}…]);
    ```

    ###### E. Nullwaarde

    Controleren op nullwaarde:

    * `IS NULL`
    * `IS NOT NULL`

    ```sql
    SELECT {kolom(men)}
    FROM {tabel}
    WHERE
    {kolom} IS [NOT] NULL;
    ```

    ##### 5.2.5 Rijen groeperen

    Rijen kan je groeperen met een `GROUP BY`-voorwaarde.

    ```sql
    -- Selectie van rijen, gegroepeerd volgens de waarde van een kolom
    SELECT {kolom(men)}
    FROM {tabel}
    WHERE {expressie}
    GROUP BY
    {kolom_1}[,
    {kolom_2}…];
    ```

    Het is te vergelijken met een `WHERE`-voorwaarde, maar laat wel het gebruik van statistische functies toe in de expressie.

    ```sql
    -- HAVING in plaats van WHERE
    SELECT {STATISTISCHE_FUNCTIE}(*)
    FROM {tabel}
    GROUP BY
    {kolom_1}[,
    {kolom_2}…]
    HAVING {expressie};
    ```

    ##### 5.2.6 Rijen sorteren

    Sorteren doe je met een `ORDER BY`-voorwaarde. Deze moet na een `WHERE`- of `GROUP BY`-voorwaarde, maar voor een `LIMIT`-voorwaarde.

    Sorteren gebeurt:

    * `ASC` *(ascending):* oplopend (0-9 en A-Z).
    * `DESC` *(descending):* aflopend (9-0 en Z-A ).

    Standaard wordt oplopend gesorteerd, daarom mag je `ASC` weglaten.

    ```sql
    -- Sorteren
    SELECT {kolom(men)}
    FROM {tabel}
    ORDER BY kolomnaamX [ASC|DESC];

    -- Met meerdere kolommen
    SELECT {kolom(men)}
    FROM {tabel}
    ORDER BY {kolom_1} [DESC][, {kolom_2} [DESC]…];
    ```
    Voorbeeld:

    mysql> SELECT *
    -> FROM users
    -> WHERE first_name LIKE 'A%'
    -> ORDER BY first_name DESC, last_name
    -> LIMIT 10;

    ##### 5.2.7 Resultaten samenvoegen

    Met `UNION` voeg je de resultaten van 2 of meer `SELECT`-query’s samen.
    Duplicaten worden uit de resultaten gefilterd. Gebruik `UNION DISTINCT` indien dit niet vanzelf gebeurt.
    De kolommen uit de andere query(’s) moeten wel gelijkaardig zijn aan die uit de eerste query.

    ```sql
    -- 2 query’s samenvoegen
    ({query_1}) UNION [DISTINCT|ALL] ({query_2})
    ORDER BY
    LIMIT

    -- Voorbeeld
    (SELECT user_familyname `name` FROM users)
    UNION
    (SELECT admin_familyname `name` FROM admins)
    ORDER BY name DESC;
    ```

    #### 5.3 Rijen **Bijwerken** [CRUD: Update]

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / UPDATE Syntax](http://dev.mysql.com/doc/refman/5.5/en/update.html)
    * `UPDATE`
    * Expressies in `SET` en `WHERE`
    * Dubbele gelijkheidstekens worden **nooit** gebruikt.
    * Zowel vergelijking als toekenning gebeurt met een enkel gelijkheidsteken.

    ```sql
    -- Rij(en) updaten in een tabel
    UPDATE {tabel}
    SET
    {kolom_1} = {waarde_1}[,
    {kolom_2} = {waarde_2}…]
    WHERE
    {kolom_8} {OPERATOR} {waarde_8}
    [AND|OR
    {kolom_9} {OPERATOR} {waarde_9}…];
    ```
    Bijvoorbeeld:

    mysql> UPDATE users
    -> SET first_name = 'Jane'
    -> WHERE user_id = 1;

    #### 5.4 Rijen **Verwijderen** [CRUD: Delete]

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / DELETE Syntax](http://dev.mysql.com/doc/refman/5.5/en/delete.html)
    ```sql
    DELETE FROM {tabel}
    WHERE {expressie(s)};
    ```
    Bijvoorbeeld:

    mysql> DELETE FROM users
    -> WHERE user_id = 1;

    ### 6. Subquery's

    Een subquery is een query in een query.

    ```sql
    -- Eenvoudige subquery
    SELECT {kolom(mem)}
    FROM {tabel}
    WHERE
    {kolom} {OPERATOR} {subquery};

    -- Voorbeeld
    SELECT *
    FROM emails
    WHERE
    id = (SELECT user_id FROM users WHERE first_name = 'Olivier' LIMIT 1);
    ```

    ### 7. Variabelen in Query's

    Soms kan het nodig zijn om variabelen te definiëren op databaseniveau. Je kan een variabele definiëren met `SET`. De variabelenaam begint met een `@`.

    ```sql
    -- Variabele definiëren
    SET @{variabele} = {waarde_of_expressie};

    -- Voorbeeld
    SET @id = (SELECT user_id FROM users WHERE first_name = 'Olivier' LIMIT 1);
    ```

    ### 8. Views

    Een view is een query die als **virtuele tabel** opgeslagen wordt. Views worden automatisch geüpdatet op de achtergrond. Views zijn vooral geschikt voor complexe query's die vaak uitgevoerd worden of heel lang duren om uit te voeren.

    #### 8.1 View **Maken**

    Begin de naam van de view met `vw_` zodat je ze makkelijk kan onderscheiden van gewone tabellen.

    ```sql
    -- Eenvoudige view maken
    CREATE VIEW vw_{view}
    AS {query};

    -- Voorbeeld
    CREATE VIEW vw_user_addresses
    AS SELECT *
    FROM users NATURAL JOIN addresses
    ORDER BY last_name, first_name;
    ```

    ### 9. Transacties

    Een **Transactie** is een geheel van SQL-statements (voor **CRUD**) dat in zijn geheel wordt uitgevoerd of helemaal niet wordt uitgevoerd.

    > De **ACID**-eigenschappen van een Transactie:
    >
    > **Atomiciteit** *(Atomicity)*
    > In zijn geheel uitgevoerd of totaal niet.
    > Verantwoordelijk: **DBMS**.
    >
    > **Consistentie** *(Consistency)*
    > Van begin tot eind uitgevoerd zonder inmenging van andere transacties.
    > Verantwoordelijk: **developer**.
    >
    > **Geïsoleerdheid** *(Isolation)*
    > Uitgevoerd alsof er geen andere transacties bestaan, ook al gebeuren die gelijktijdig.
    > Verantwoordelijk: **DBMS**.
    >
    > **Duurzaamheid** *(Durablility)*
    > Wijzigingen mogen niet verloren gaan door een defect of fout.
    > Verantwoordelijk: **DBMS**.
    **Geld overschrijven** is een typisch voorbeeld van een transactie:

    * Geld moet van de ene rekening naar de andere gaan.
    * Op geen enkel moment mag er geld uit het systeem verdwijnen.
    * Als iets misloopt, dan moet het systeem naar de oude toestand terugkeren.

    Een transactie begint met `START TRANSACTION` en wordt ofwel ongedaan gemaakt met `ROLLBACK` of definitief uitgevoerd met `COMMIT`.

    ```sql
    -- 1. Een transactie beginnen
    START TRANSACTION;

    -- 2. SQL-statements

    -- 3.a Om de wijzigingen ongedaan te maken
    ROLLBACK;

    -- 3.b Om de wijzigigen definitief te maken
    COMMIT;
    ```

    > **OPGELET:** Of een tabel Transacties ondersteunt hangt af van de gebruikte **Storage Engine**. Zie het betreffende hoofdstuk hieronder.

    V. Bijlagen
    -------------

    ### 1. Datatypes

    De database slaat gegevens op volgens een bepaald **datatype** dat vooraf bepaald moet worden. Dit datatype heeft gevolgen voor de snelheid waarmee de gegevens opgezocht kunnen worden en de grootte van de nodige opslagruimte.

    Probeer een datatype te kiezen dat zo goed mogelijk past bij het soort gegevens:

    * Kleinst mogelijke opslagruimte.
    * Voldoet aan de vereisten: snelheid, precisie, doorzoekbaarheid …
    * Houd er ook rekening mee dat vereisten in de toekomst kunnen wijzigen.
    * Een database wijzigen die reeds miljoenen rijen bevat is tijdrovend en bovendien is wijzigingen uitvoeren misschien te riskant.

    #### 1.1 Numeriek

    ##### 1.1.1 Integers

    ###### A. Gehele getallen
    [Gehele getallen](http://dev.mysql.com/doc/refman/5.5/en/integer-types.html) *(Integers)* stellen een exacte waarde voor.

    De integerdatatypes van klein naar groot:

    * `TINYINT`;
    * `SMALLINT`;
    * `MEDIUMINT`;
    * `INT` (of `INTEGER`);
    * `BIGINT`.

    Tussen ronde haakjes kan `({n})` het minimum aantal getoonde tekens opgegeven worden. Dit heeft **geen invloed op de maximumwaarde** van het bereik, maar heeft enkel invloed in combinatie met `ZEROFILL`, waarbij de niet gebruikte plaatsen tot het n-de teken met een `0` opgevuld worden.

    ```sql
    -- Integers
    {DATATYPE}
    {DATATYPE}({n})
    {DATATYPE}({n}) ZEROFILL
    {DATATYPE}({n}) UNSIGNED
    {DATATYPE}({n}) UNSIGNED ZEROFILL
    ```

    ###### B. Booleaanse waarden

    Voor MySQL is een booleaanse waarde de kleinste integer (`TINYINT`) die slechts 1 teken toont.

    * **ONWAAR:** `0`
    * **WAAR:** alle waarden die niet `0` zijn, bijv. `1`, `-3` of `9`

    ```sql
    -- Synoniemen booleaanse waarde
    -- opslag: 1 byte (8 bits!)
    BOOL
    BOOLEAN
    TINYINT(1)
    ```

    ###### C. Overzicht integerdatatypes

    | Datatype | Signed | Opslagruimte | Minimumwaarde | Maximumwaarde |
    | -----------:|-----------:|-------------:|-----------------------:|-----------------------:|
    | `TINYINT` | | 1 byte | `-128` | `127` |
    | `TINYINT` | `UNSIGNED` | 1 byte | `0` | `255` |
    | `SMALLINT` | | 2 bytes | `-32768` | `32767` |
    | `SMALLINT` | `UNSIGNED` | 2 bytes | `0` | `65535` |
    | `MEDIUMINT` | | 3 bytes | `-8388608` | `8388607` |
    | `MEDIUMINT` | `UNSIGNED` | 3 bytes | `0` | `16777215` |
    | `INT` | | 4 bytes | `-2147483648` | `2147483647` |
    | `INT ` | `UNSIGNED` | 4 bytes | `0` | `4294967295` |
    | `BIGINT` | | 8 bytes | `-9223372036854775808` | `9223372036854775807` |
    | `BIGINT` | `UNSIGNED` | 8 bytes | `0` | `18446744073709551615` |


    ##### 1.1.2 Floating-point
    [Zwevendekommagetallen](http://dev.mysql.com/doc/refman/5.5/en/floating-point-types.html) *(floating-point values)* hebben een waarde bij benadering.

    `FLOAT({p})`

    * `{p}`: Precisie

    `({m},{d})`

    * `{m}`: Mantisse (totaal aantal cijfers)
    * `{d}`: Decimaal (**maximaal** aantal cijfers na de komma)

    ```sql
    -- enkele-precisiewaarde
    -- {p}: 0 t.e.m. 23
    -- 4 bytes opslagruimte
    FLOAT
    FLOAT({p})
    FLOAT({m},{d})

    -- 0.00 tot 9999.99
    FLOAT(6,2)

    -- dubbele-precisiewaarde
    -- {p}: 24 t.e.m. 53
    -- 8 bytes opslagruimte
    DOUBLE
    DOUBLE PRECISION
    FLOAT({p})
    ```

    ##### 1.1.3 Decimal values

    [Vastekommagetallen](http://dev.mysql.com/doc/refman/5.5/en/precision-math-decimal-characteristics.html) *(Decimal values)* Hebben een exacte waarde.

    > **Tip:** Gebruik vastekommagetallen voor valuta, want bij geldtransacties mogen geen afrondingsfouten ontstaan.
    `DECIMAL({m},{d})`

    * `{m}`: Mantisse (totaal aantal cijfers)
    * `{d}`: Decimaal (**exact** aantal cijfers na de komma)


    ```sql
    -- {m}: 1 tot 65
    -- {d}: 0 tot m
    -- standaardwaarde {m} is 10
    DECIMAL
    DECIMAL({m}) -- = DECIMAL({m},0)
    DECIMAL({m},{d})
    ```

    #### 1.2 Strings

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / String Types](http://dev.mysql.com/doc/refman/5.5/en/string-types.html)
    ##### 1.2.1 Tekenstrings

    Wordt gebruikt voor tekst.

    ```sql
    -- Vaste lengte
    -- {n}: van 0 tot 255
    -- opslagruimte: {n} bytes
    CHAR({n})

    -- Variabele lengte
    -- {n}: van 0 tot 65535
    -- opslagruimte:
    -- (lengte + 1) bytes als {n} <= 255
    -- (lengte + 2) bytes als 255 < {n}
    -- lengte <= {n}
    VARCHAR({n})
    TINYTEXT
    TEXT
    MEDIUMTEXT
    LONGTEXT
    ```

    | Datatype | Alternatief | Opslagruimte | Maximumlengte |
    |:-----------------|-------------:|-------------------:|--------------:|
    | `CHAR(1)` | | 1 byte | `1`|
    | `CHAR(255)` | | (lengte) bytes | `255`|
    | `VARCHAR(255)` | `TINYTEXT` | (lengte + 1) bytes | `255`|
    | `VARCHAR(65535)` | `TEXT` | (lengte + 2) bytes | `65535`|
    | | `MEDIUMTEXT` | (lengte + 3) bytes | `16777215`|
    | | `LONGTEXT` | (lengte + 4) bytes | `4294967295`|


    ##### 1.2.2 Bytestrings
    Wordt gebruikt om binaire (niet-tekstuele) gegevens op te slaan.

    - Geen tekenset.
    - Alfabetische sorteringen en vergelijkingen gebeuren op basis van de numerieke waarden van de bytes.
    - Voor binaire (niet-tekstuele) gegevens. Bijvoorbeeld foto- of andere bestanden.

    > **BLOB:** Binary Large Object
    ```sql
    -- Vaste lengte
    -- {n}: 0 tot 255
    -- opslagruimte: {n} bytes
    BINARY({n})

    -- Variabele lengte
    -- {n}: van 0 tot 65535
    -- opslagruimte:
    -- (lengte + 1) bytes als {n} <= 255
    -- (lengte + 2) bytes als 255 < {n}
    -- lengte <= {n}
    VARBINARY({n})
    TINYBLOB
    BLOB
    MEDIUMBLOB
    LONGBLOB
    ```

    | Datatype | Alternatief | Opslagruimte | Maximumlengte |
    |:-------------------|-------------:|-------------------:|--------------:|
    | `BINARY(1)` | | 1 byte | `1`|
    | `BINARY(255)` | | (lengte) bytes | `255`|
    | `VARBINARY(255)` | `TINYBLOB` | (lengte + 1) bytes | `255`|
    | `VARBINARY(65535)` | `BLOB` | (lengte + 2) bytes | `65535`|
    | | `MEDIUMBLOB` | (lengte + 3) bytes | `16777215`|
    | | `LONGBLOB` | (lengte + 4) bytes | `4294967295`|

    ### 2. Operatoren

    #### 2.1 SQL-92 Operatoren

    SQL-92 was de derde revisie en meteen ook een grote. Deze standaard uit 1992 wordt soms SQL2 genoemd. Nog veel RDBMS’en gebruiken op deze standaard geïnspireerde SQL.

    | Operator | Betekenis | SQL-92 |
    |:---------|:----------------------|:------:|
    | `… = …` | gelijk aan/toekenning | Ja |
    | `… < …` | kleiner dan | Ja |
    | `… > …` | groter dan | Ja |
    | `… <= …` | kleiner of gelijk aan | Ja |
    | `… >= …` | groter of gelijk aan | Ja |
    | `… <> …` | niet gelijk aan | Ja |
    | `… != …` | niet gelijk aan | Nee |

    | Booleaanse waarde | Betekenis |
    |:------------------|:------------|
    | `UNKOWN` | nullwaarde
    | `FALSE` | 0
    | `TRUE` | 1


    ```sql
    -- Boolaanse waarden
    … IS [NOT] {bool}

    -- Is nullwaarde?
    … IS [NOT] NULL

    -- In een bereik van getallen
    … [NOT] BETWEEN min AND max

    -- In een lijst van waarden
    … [NOT] IN(waarde1[, waarde2…])
    ```

    #### 2.2 Patroonherkenning

    ##### 2.2.1 Eenvoudige patroonherkenning

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / String Comparison Functions](http://dev.mysql.com/doc/refman/5.5/en/string-comparison-functions.html)
    Eenvoudige patroonherkenning gebeurt met `LIKE` of `NOT LIKE`.

    ```sql
    -- Eenvoudige patroonherkenning
    … [NOT] LIKE '{patroon}'

    -- Patronen
    % -- 0 of meer tekens
    _ -- Exact 1 teken

    -- Selecteer zowel Tim, Timoty, Tom als Tomas.
    SELECT
    'Tanya' LIKE 'T_m%',
    'Tim' LIKE 'T_m%',
    'Timoty' LIKE 'T_m%',
    'Tom' LIKE 'T_m%',
    'Tomas' LIKE 'T_m%';
    ```
    Bijvoorbeeld:

    mysql> SELECT *
    -> FROM users
    -> WHERE first_name LIKE 'T_m%';

    ##### 2.2.2 Reguliere expressies.

    > **Zie ook:**
    >
    > * [MySQL / MySQL 5.5 Reference Manual / Regular Expressions](http://dev.mysql.com/doc/refman/5.5/en/regexp.html)
    Patroonherkenning met reguliere expressies gebeurt met `REGEXP` of `NOT REGEXP`.

    ```sql
    -- Patroonherkenning met reguliere expressies
    … [NOT] REGEXP '{reguliere_expressie}'

    -- Reguliere expressies
    [{tekenset}] -- Exact 1 teken uit de tekenset
    [^{tekenset}] -- Exact 1 teken niet uit de tekenset

    -- Selecteer zowel Tim en Tom.
    SELECT
    'Tam' REGEXP 'T[^io]m',
    'Tam' REGEXP 'T[io]m',
    'Tim' REGEXP 'T[io]m',
    'Tom' REGEXP 'T[io]m';
    ```
    Bijvoorbeeld:

    mysql> SELECT *
    -> FROM users
    -> WHERE first_name REGEXP 'T[io]m';

    #### 2.3 Logische operatoren

    > Zie ook:
    >
    > * [MySQL / MySQL 5.5 Reference Manual / Logical Operators](http://dev.mysql.com/doc/refman/5.5/en/logical-operators.html)
    Logische operatoren hebben als resultaat **WAAR** (`1` of `TRUE`), **ONWAAR** (`0` of `FALSE`) of **nullwaarde** (`NULL`) en worden van **links naar rechts** geëvalueerd.

    * `{expressie_1} AND {expressie_2}`
    * `{expressie_1} OR {expressie_2}`
    * `{expressie_1} XOR {expressie_2}`

    ##### 2.3.1 Logische EN-operator

    > In de Booleaanse algebra geldt:
    >
    > | $ p $ | $ q $ | $ (p \land q) $ |
    > |:-----:|:-----:|:---------------:|
    > | $ 0 $ | $ 0 $ | $ 0 $ |
    > | $ 0 $ | $ 1 $ | $ 0 $ |
    > | $ 1 $ | $ 0 $ | $ 0 $ |
    > | $ 1 $ | $ 1 $ | $ 1 $ |
    >
    > Beide termen moeten WAAR zijn.
    ```sql
    -- Beide expressies moeten WAAR zijn
    {expressie_1} AND {expressie_2}
    ```

    Bijvoorbeeld:

    mysql> SELECT
    -> 0 AND 0,
    -> 0 AND 1,
    -> 1 AND 0,
    -> 1 AND 1;

    | Expressie | Resultaat |
    |-----------|:---------:|
    | `0 AND 0` | `0` |
    | `0 AND 1` | `0` |
    | `1 AND 0` | `0` |
    | `1 AND 1` | `1` |


    ##### 2.3.2 Logische OF-operator

    > In de Booleaanse algebra geldt:
    >
    > | $ p $ | $ q $ | $ (p \lor q) $ |
    > |:-----:|:-----:|:--------------:|
    > | $ 0 $ | $ 0 $ | $ 0 $ |
    > | $ 0 $ | $ 1 $ | $ 1 $ |
    > | $ 1 $ | $ 0 $ | $ 1 $ |
    > | $ 1 $ | $ 1 $ | $ 1 $ |
    >
    > Minstens één van de termen moet WAAR zijn.

    ```sql
    -- Minstens één van de expressies moet waar zijn
    {expressie_1} OR {expressie_2}
    ```

    Bijvoorbeeld:

    mysql> SELECT
    -> 0 OR 0,
    -> 0 OR 1,
    -> 1 OR 0,
    -> 1 OR 1;

    | Expressie | Resultaat |
    |-----------|:---------:|
    | `0 OR 0` | `0` |
    | `0 OR 1` | `1` |
    | `1 OR 0` | `1` |
    | `1 OR 1` | `1` |

    ##### 2.3.2 Logische Exclusieve OF-operator

    > In de Booleaanse algebra geldt:
    >
    > | $ p $ | $ q $ | $ (p \oplus q) $ |
    > |:-----:|:-----:|:----------------:|
    > | $ 0 $ | $ 0 $ | $ 0 $ |
    > | $ 0 $ | $ 1 $ | $ 1 $ |
    > | $ 1 $ | $ 0 $ | $ 1 $ |
    > | $ 1 $ | $ 1 $ | $ 0 $ |
    >
    > Beide termen moeten verschillend zijn.
    ```sql
    -- Beide expressies moeten een verschillende logische uitkomst hebben
    {expressie_1} XOR {expressie_2}
    ```
    Bijvoorbeeld:

    mysql> SELECT
    -> 0 XOR 0,
    -> 0 XOR 1,
    -> 1 XOR 0,
    -> 1 XOR 1;

    | Expressie | Resultaat |
    |-----------|:---------:|
    | `0 XOR 0` | `0` |
    | `0 XOR 1` | `1` |
    | `1 XOR 0` | `1` |
    | `1 XOR 1` | `0` |


    ### 3. Functies

    #### 3.1 Statistische functies

    Aggregate functions

    Te gebruiken met een GROUP BY met zowel:
    SELECT-clausule
    HAVING-clausule

    ```sql
    AVG() -- Gemiddelde
    COUNT() -- Aantal
    COUNT(DISTINCT) -- Aantal unieke
    MAX() -- Grootste
    MIN() -- Kleinste
    SUM() -- Som
    ```

    #### 3.2 Numerieke functies
    Deze functies mag je overal toepassen.

    ```sql
    -- Afronden
    ROUND({getal}) -- afronden
    CEIL({getal}) -- naar boven afronden
    FLOOR({getal}) -- naar beneden afronden

    -- Aantal decimalen ({d})
    TRUNCATE({getal},{d})
    ```

    #### 3.3 Datum- en tijdfuncties
    Deze functies mag je overal toepassen.

    ```sql
    CURDATE() -- Datum nu
    CURTIME() -- Tijd nu
    NOW() -- Datum+tijd nu
    YEAR({datum}) -- Jaartal

    -- Datum formatteren
    DATE_FORMAT({datum}, {formaat})

    -- Huidige dag, datum en tijd
    SELECT DATE_FORMAT(NOW(), '%a %d/%m/%Y %H:%i:%S');
    ```

    #### 3.4 Stringfuncties
    Deze functies mag je overal toepassen.

    ```sql
    CONCAT({tekenstring_1}[, {tekenstring_2}…]) -- Concateneren (samenvoegen)
    LCASE({tekenstring}) -- Onderkast
    LENGTH({tekenstring}) -- Stringlengte
    UCASE({tekenstring}) -- Kapitalen
    TRIM({tekenstring}) -- Spaties trimmen
    SUBSTR({tekenstring},{positie}) -- Substring
    ```

    ### 4. Storage Engines

    MySQL Server gebruikt **Storage Engines** om tabellen op te slaan. Een storage engine bepaalt het **Tabeltype**.

    * Per tabel kan een andere engine gebruikt worden.
    * Elke Storage Engine of Tabeltype heeft voor- en nadelen.
    * De beschikbare engines zijn afhankelijk van de MySQL-installatie!

    **Tabeltypes:**

    * **NTST** *(Non-Transaction-Safe Tables)*
    * Sneller;
    * Kleiner opslaggeheugen nodig;
    * Kleiner werkgeheugen nodig.
    * **TST** *(Transaction-Safe Tables)*
    * Ondersteunt **Transacties**;
    * Veiliger: crashbestendig.

    | Engine | Tabeltype |
    |:---------|:----------|
    | `InnoDB` | TST |
    | `Memory` | NTST |
    | `MyISAM` | NTST |

    Naast de bovenstaande engines, zijn er nog vele andere:

    * `Archive`
    * `BerkeleyDB`
    * `CSV`
    * `IBMDB2I`
    * `Merge`
    *

    ```sql
    -- Tabel maken met bepaalde storage engine
    CREATE TABLE users (id)
    ENGINE = MyISAM;

    -- Storage engine wijzigen
    ALTER TABLE users
    ENGINE = InnoDB;

    -- Tabel in het werkgeheugen tot de server herstart.
    ALTER TABLE users
    ENGINE = Memory;
    ```

    ### 5. Optimalizeren van Query's

    Met `EXPLAIN` kun je nagaan hoe MySQL de query's uitvoert:

    * Welke kolommen komen in aanmerking voor een `INDEX`.
    * Hoe verloopt een `JOIN`.

    Met `EXPLAIN EXTENDED` krijg je meer uitgebreide informatie.

    ```sql
    -- Informatie over de query
    EXPLAIN [EXTENDED] {query};

    -- Voorbeeld
    EXPLAIN
    SELECT * FROM users
    ORDER BY last_name;
    ```