Informaticasite van het Lauwers College te Buitenpost                 © R.J. van der Beek
 

SQL

SQL, de afkorting van Structured Query Language, is een vraagtaal waarmee gegevens van databases kunnen worden opgevraagd.
Daarvoor is een standaard ontwikkeld waaraan alle databaseontwikkelaars zich in principe moeten houden.
Toch zijn er enkele verschillen in de SQL-lidsoorten bij de verschillende DBMS'en (database management systemen)
Bepaalde commando's werken bij de ene DBMS wel en bij andere niet.

De taal SQL kan onderverdeeld worden in een aantal subtalen.
  • DML: Data Manipulation Language.
    Dit is het gedeelte van SQL waarbij je gegevens in de database toevoegt, gegevens uit de database opvraagt, gegevens in de database bewerkt.
  • DDL: Data Defenition Language.
    Met dit gedeelte maak en bewerk je de structuur van de database en de databasetabellen.
De commando's die gebruikt worden heten query's.

  § 1. De tabellen


Misschien ontdek je bij het uitproberen van de queries dat de tabellen niet meer de juiste gegevens bevatten. Je kunt namelijk zelf de inhoud van de tabellen veranderen m.b.v. INSERT, UPDATE en DELETE.
Wil je dat de tabellen de oorspronkelijke gegevens weer bevatten (zoals hieronder), klik dan op oorspronkelijke tabellen herstellen


We gaan de eerste voorbeelden uitleggen aan de hand van de volgende tabel.
Deze tabel noemen we leden, en het is een tabel van de database met de naam Tennisvereniging:

lidnrnaamwoonplaatsgeborenleeftijdlidsoortscore
1AnnieBuitenpost1944-06-0262senior2075
2WillemVeenklooster1992-09-1314jeugdlid987
3HillegienKollum1968-01-1138senior1598
4MargreetKollum1980-09-1826aktielid234
5ElineBuitenpost1996-11-0410jeugdlid435
6GerritTwijzel1958-05-0448senior5989
7FemkeAugustinusga1993-09-1913jeugdlid798
8DonaBurum2000-05-156mkmt155
9ChrisBurum1998-12-127mkmt236
10DieuwkeBuitenpost1959-09-0647senior7345
11KeesVeenklooster1965-07-2741senior6345
12LeonAugustinusga1980-06-0626aktielid380
13SabineDrogeham1970-11-1036senior4999
14FemkeDrogeham1979-07-0627senior3768

Vanaf § 6 maken we ook gebruik van de volgende tabellen:
Tabel competitiesoort:
soortspeeldagaanvoerder
HDdonderdag11
HEzaterdag6
DDdinsdag3
JDwoensdag2
GDzaterdag 

en tabel competitielid:
compnrlidnrsoort
16HD
211HD
312HD
46HE
511HE
61DD
73DD
87DD
92JD
107JD

  § 2. Select, distinct, order by

Als je een lijstje van de namen en de scores uit de tabel wilt dan kan dat met de volgende query:

SELECT naam, score FROM leden ;

Het resultaat is dan:
naamscore
Annie2075
Willem987
Hillegien1598
Margreet234
Eline435
Gerrit5989
Femke798
Dona155
Chris236
Dieuwke7345
Kees6345
Leon380
Sabine4999
Femke3768

Als je de lidsoorten uit de tabel wilt dan kan dat met de volgende query:

SELECT lidsoort FROM leden ;

Het resultaat is dan:

lidsoort
senior
jeugdlid
senior
aktielid
jeugdlid
senior
jeugdlid
mkmt
mkmt
senior
senior
aktielid
senior
senior
DISTINCT
Je ziet dat sommige lidsoorten meerdere keren voorkomen.
Dat komt omdat van elke rij de lidsoort wordt afgedrukt.
Om te voorkomen dat we dubbele resultaten krijgen gebruiken we het commando DISTINCT. De query komt er dan als volgt uit te zien:

SELECT DISTINCT lidsoort FROM leden ;

Het resultaat is dan:

lidsoort
senior
jeugdlid
aktielid
mkmt

Als je alle gegevens uit alle kolommen wilt laten afdrukken dan kun je alle kolommen noemen in je query, dus:

SELECT lidnr,naam,woonplaats,geboren,leeftijd,lidsoort,score FROM leden ;

Of je maakt gebruik van een sterretje (*). De query ziet er dan als volgt uit:

SELECT * FROM leden ;

Je krijgt dan de volledige tabel zien die in paragraaf 1 staat.
ORDER BY
Gegevens uit een tabel kun je ook laten sorteren, daarvoor gebruik je het commando ORDER_BY.
Het sorteren kan op twee manieren: oplopend en aflopend, in het engels is dat ascending en descending. In SQL wordt dat afgekort tot ASC en DESC

Stel je wilt een lijstje van de namen uit de ledentabel met de scores, en dan gesorteerd op de scores met de persoon met de hoogste score bovenaan.
De query komt er dan zo uit te zien:

SELECT naam,score FROM leden ORDER BY score DESC ;

Je krijgt hetzelfde resultaat met de volgende query:
SELECT naam,score FROM leden ORDER BY 2 DESC ;

De 2 in deze query staat voor de als tweede genoemde kolom, dus de score.

Je krijgt dan het volgende lijstje:

naamscore
Dieuwke7345
Kees6345
Gerrit5989
Sabine4999
Femke3768
Annie2075
Hillegien1598
Willem987
Femke798
Eline435
Leon380
Chris236
Margreet234
Dona155

Als je geen asc of desc bij order by gebruikt dan wordt er oplopend gesorteerd, je hoeft ASC dus eigenlijk nooit te gebruiken.

Opgaven:
  1. Geef de query voor een lijstje van alle leden, met alle gegevens, gesorteerd op leeftijd, en wel zo dat de oudste bovenaan staat.
  2. Geef de query voor een lijstje met de naam, de woonplaats, en de score van alle leden, gesorteerd op de naam.
  3. Geef de query voor een lijstje van alle plaatsen waar leden vandaan komen, alfabetisch gerangschikt.
Je kunt de queries hier uitproberen. Voer de query hieronder in, dan wordt hij door MySQL verwerkt.

Voer hier de query in:


Misschien ontdek je dat de tabellen niet meer de juiste gegevens bevatten. Je kunt namelijk zelf de inhoud van de tabellen veranderen m.b.v. INSERT, UPDATE en DELETE.
Wil je dat de tabellen de oorspronkelijke gegevens weer bevatten, klik dan op oorspronkelijke tabellen herstellen

  § 3. Voorwaarden: where, and, or, not, like, is null, limit

Als je bepaalde rijen wilt laten afdrukken die voldoen aan één of meerdere voorwaarden, dan gebruik je het commando WHERE.
In het volgende voorbeeld maken we een lijstje van de leden die in Buitenpost wonen.
De query wordt:

SELECT naam,lidsoort FROM leden WHERE woonplaats = 'Buitenpost' ;

We krijgen dan dit resultaat:

naamlidsoort
Anniesenior
Elinejeugdlid
Dieuwkesenior

De basis syntax voor de query is:

SELECT kolommen FROM tabel WHERE voorwaarde ;

In de voorwaarde zit altijd een operator, je kunt de volgende operatoren in SQL gebruiken:

operator betekenis
= is gelijk aan
< is kleiner dan
> is groter dan
<= is kleiner of gelijk aan
>= is groter of gelijk aan
<> is niet gelijk aan
between ligt tussen
in is één van de volgende waarden

AND, OR, NOT
Als er aan meerdere voorwaarden moet worden voldaan kun je gebruik maken van AND, OR en NOT.

Als je alle namen wilt hebben van de leden die 30 jaar of ouder zijn en die niet in Buitenpost wonen, dan kan dat met de volgende query:

SELECT naam, leeftijd, woonplaats FROM leden WHERE leeftijd >= 30 AND woonplaats <> 'Buitenpost' ;

Denk er om dat 30 niet tussen aanhalingstekens geplaatst moet worden, omdat de leeftijd numeriek is.
(Lidnr, leeftijd en score zijn numeriek, dus getallen. Geboren is van het type date, naam, woonplaats en lidsoort zijn van het type tekst)

Je krijgt dan het volgende lijstje:

naamleeftijdwoonplaats
Hillegien38Kollum
Gerrit48Twijzel
Kees41Veenklooster
Sabine36Drogeham

Als je alleen de namen willen hebben van de leden die ouder dan 60 jaar zijn of een score van meer dan 5000 hebben, dan kun je die krijgen met de volgende query:

SELECT naam, leeftijd, score FROM leden WHERE leeftijd > 60 OR score > 5000 ;

Deze query heeft als resultaat:

naamleeftijdscore
Annie622075
Gerrit485989
Dieuwke477345
Kees416345

Annie komt in het lijstje voor omdat ze ouder dan 60 is. En de anderen voldoen aan de tweede voorwaarde, hun score zit namelijk boven de 5000.

BETWEEN
Met BETWEEN moet de kolomwaarde tussen twee waarden liggen.
Stel dat je een lijstje wilt van alle leden die een leeftijd hebben tussen de 20 en de 40. Dat kan met de volgende query:

SELECT naam, leeftijd FROM leden WHERE leeftijd BETWEEN 20 AND 40 ;

Het resultaat is:
naamleeftijd
Hillegien38
Margreet26
Leon26
Sabine36
Femke27


IN
Met het commando IN kun je hetzelfde bereiken als met OR maar de query wordt dan korter.
Als je de leden wilt afdrukken die in Kollum of Buitenpost of Veenklooster wonen, dan kun je als voorwaarde gebruiken:
where woonplaats="Kollum" or woonplaats="Buitenpost" or woonplaats="Veenklooster")
Maar het kan ook met de volgende voorwaarde:
where woonplaats in ("Kollum", "Buitenpost", "Veenklooster")

SELECT naam, woonplaats FROM leden WHERE woonplaats IN ('Kollum', 'Buitenpost','Veenklooster') ;

Resultaat:
naamwoonplaats
AnnieBuitenpost
WillemVeenklooster
HillegienKollum
MargreetKollum
ElineBuitenpost
DieuwkeBuitenpost
KeesVeenklooster

NOT
Met NOT kun je de leden krijgen die niet aan een bepaalde voorwaarde voldoen.
Stel dat je alle leden wilt hebben die niet in Buitenpost wonen.
Dat kan m.b.v. de volgende query:

SELECT * FROM leden WHERE NOT woonplaats = 'Buitenpost' ;

Je kunt hetzelfde lijstje krijgen m.b.v. deze query:

SELECT * FROM leden WHERE woonplaats <> 'Buitenpost' ;

Het resultaat is:

lidnrnaamwoonplaatsgeborenleeftijdlidsoortscore
2WillemVeenklooster1992-09-1314jeugdlid987
3HillegienKollum1968-01-1138senior1598
4MargreetKollum1980-09-1826aktielid234
6GerritTwijzel1958-05-0448senior5989
7FemkeAugustinusga1993-09-1913jeugdlid798
8DonaBurum2000-05-156mkmt155
9ChrisBurum1998-12-127mkmt236
11KeesVeenklooster1965-07-2741senior6345
12LeonAugustinusga1980-06-0626aktielid380
13SabineDrogeham1970-11-1036senior4999
14FemkeDrogeham1979-07-0627senior3768

LIKE
Met LIKE kun je selecteren op gedeelten van de tekst.
Stel dat je een lijstje wilt van de leden waarvan de naam met een D begint. Dat kan met de volgende query:

SELECT * FROM leden WHERE naam LIKE 'D%' ;

Je ziet dat er na LIKE staat: 'D%'
Het % teken is een zogenaamde wildcard en staat voor een willekeurig aantal tekens.
Het betekent dus dat de naam met een D moet beginnen, en wat er achter staat doet er niet toe, dat mag alles zijn.
(In Access moet je in plaats van het procentteken % een sterretje * gebruiken)
Je krijgt dan het volgende:

lidnrnaamwoonplaatsgeborenleeftijdlidsoortscore
8DonaBurum2000-05-156mkmt155
10DieuwkeBuitenpost1959-09-0647senior7345

Als je alle namen en hun woonplaatsen wilt hebben van mensen die een dubbele e (ee) in hun woonplaats hebben, dan gebruik je de volgende query:

SELECT naam, woonplaats FROM leden WHERE woonplaats LIKE '%ee%' ;

Deze query levert onderstaand resultaat op:

naamwoonplaats
WillemVeenklooster
KeesVeenklooster

In combinatie met LIKE kun je nog een andere wildcard gebruiken, namelijk het teken _ , de underscore. Dat teken staat voor één willekeurig teken (en een procentteken (%) staat voor meerdere willekeurige tekens (dat kan ook één of nul zijn).
(In Access moet je in plaats van het underscoreteken _ een procentteken % gebruiken)

Stel dat we alle namen willen hebben van de leden waarvan de naam uit vier letters bestaat. De query wordt dan:

SELECT naam FROM leden WHERE naam LIKE '____' ;
(Achter LIKE staan vier underscore-tekens achter elkaar!)

Dit geeft als resultaat:

naam
Dona
Kees
Leon

We kunnen de beide wildcards ook combineren. Stel dat we de namen van de leden willen hebben waarvan de voorlaatste letter een e is.
Die krijg je m.b.v. de volgende query:

SELECT naam FROM leden WHERE naam LIKE '%e_' ;

Dit geeft als resultaat:

naam
Willem
Hillegien
Margreet
Kees

IS NULL
Als je wilt controleren m.b.v. SQL of een kolom is ingevuld dan gebruik je IS NULL
Je kunt bijvoorbeeld de volgende query uitproberen:

SELECT naam FROM leden WHERE score IS NULL ;

Het resultaat is dan dat er geen enkele rij wordt afgedrukt, want overal is een score ingevuld.

LIMIT
Je kunt het aantal rijen dat wordt afgedrukt beperken m.b.v. LIMIT.
Stel dat je de naam van de persoon wilt hebben die de hoogste score heeft. Je moet dan een query maken die sorteert op score, en die maar één rij afdrukt.
De query komt er dan zo uit te zien:

SELECT naam, score FROM leden ORDER BY score DESC LIMIT 1 ;

Deze query levert het volgende op:

naamscore
Dieuwke7345

LIMIT 1 geeft aan dat de query moet stoppen na de eerste rij.

Stel dat je de drie mensen wilt hebben, die wat score betreft op de plaatsen 3, 4 en 5 staan. Dus de twee hoogsten niet, maar de drie die daarop volgen. Dat kan met de volgende query:

SELECT naam, score FROM leden ORDER BY score DESC LIMIT 2,3 ;

Je ziet dat er nu na LIMIT 2,3 staat; dat betekent dat er wordt begonnen met rij nummer 2 (dat is de derde rij want er wordt begonnen met tellen bij 0, de eerste rij heeft nummer 0 en de tweede rij heeft nummer 1), en er worden 3 rijen afgedrukt.
Bovenstaande query geeft als resultaat:
naamscore
Gerrit5989
Sabine4999
Femke3768

Het gebruik van LIMIT is geen ANSI-SQL, maar een functie van MySQL.
Het zal dus waarschijnlijk niet in ander DBMS'en werken.

Opgaven:
  1. Geef de query voor een lijstje van alle leden uit Veenklooster, geef de naam, de woonplaats, en de score.
  2. Geef de query voor een lijstje van alle leden (geef de naam en de leeftijd), die ouder dan 20 jaar zijn, en waarvan de naam met een F begint
  3. Geef de query voor een lijstje van alle leden (geef de naam, de leeftijd en de lidsoort), die geen aktielid zijn, en die jonger dan 20 jaar zijn.
  4. Geef de query voor een lijstje van alle jeugdleden (geef de naam, de leeftijd,de lidsoort en de score), gesorteerd op score, en wel zo dat degene met de hoogste score bovenaan staat.
  5. Geef de query voor de competitiesoort(en), waarvoor nog geen aanvoerder is vastgelegd.
  6. Geef de query voor de competitiesoorten, die op zaterdag worden gespeeld.
Je kunt de queries hier uitproberen. Voer de query hieronder in, dan wordt hij door MySQL verwerkt.

Voer hier de query in:

  § 4. Functies in SQL, alias (AS)

De taal SQL kent een aantal functies die je kunt gebruiken om berekeningen uit te laten voeren, of om het aantal rijen te tellen, of om de kolommen op een bepaalde manier af te drukken.

Als je de volgende query gebruikt dan wordt de gemiddelde score van alle leden afgedrukt:
(AVG is de afkorting van average, en dat betekent: gemiddelde)

SELECT AVG(score ) FROM leden ;

Het resultaat van die query is:

AVG(score )
2524.5714

COUNT
Een ander voorbeeld van een functie in SQL: met de volgende query wordt het aantal leden afgedrukt:

SELECT COUNT(* ) FROM leden ;

Het resultaat van die query is:

COUNT(* )
14

AS
Je ziet dat de kop van de lijsten hierboven, bij het gebruik van functies, weinigzeggend is voor mensen die geen verstand hebben van SQL.
Je kunt de namen van de kolommen een andere naam geven, en die naam verschijnt dan ook boven de lijst.
Die andere naam wordt dan wel een alias genoemd, en dat kan met behulp van AS.

Als je de vorige sql-query als volgt wijzigt:

SELECT COUNT(*) AS aantal_leden FROM leden ;

dan is het resultaat:

aantal_leden
14

En als je de query daarvoor verandert in:

SELECT AVG (score) AS gemiddelde_score FROM leden ;

dan is het resultaat:

gemiddelde_score
2524.5714

Een aantal paragrafen verderop, bij het gebruik van meerdere tabellen door elkaar, zul je zien dat kolommen hernoemen m.b.v. AS ook heel handig is om queries overzichtelijk te houden.

ROUND
Nog een voorbeeld van een functie in SQL: ROUND(kolom, aantal decimalen) zorgt ervoor dat de getallen in de betreffende kolom worden afgerond op het aantal decimalen dat je hebt opgegeven.

Voorbeeld:

SELECT ROUND(AVG(leeftijd), 1) AS gemiddelde_leeftijd FROM leden ;

levert als resultaat de gemiddelde leeftijd, afgerond op één decimaal:

gemiddelde_leeftijd
28.6

LEN
Een andere functie is LEN(kolomnaam) : geeft het aantal tekens van de woorden in de kolom.
In MySQL wordt gebruik gemaakt van de functie LENGTH( ) in plaats van LEN( )

Voorbeeld:

SELECT naam, LEN(naam) AS aantal_letters_van_de_naam FROM leden ;

geeft als resultaat :

naamaantal_letters_van_de_naam
Annie5
Willem6
Hillegien9
Margreet8
Eline5
Gerrit6
Femke5
Dona4
Chris5
Dieuwke7
Kees4
Leon4
Sabine6
Femke5

UCASE
Nog een voorbeeld: UCASE(kolomnaam) geeft de tekst in de kolom in hoofdletters.

SELECT UCASE(naam ) FROM leden WHERE woonplaats = 'Buitenpost' ;

geeft als resultaat:

UCASE(naam )
ANNIE
ELINE
DIEUWKE

CURRENT_DATE
Er zijn ook speciale functies voor de datum en de tijd.
Voorbeeld: CURRENT_DATE( ) geeft de huidige systeemdatum als resultaat.

De query:

SELECT CURRENT_DATE() AS datum ;

Resultaat:
datum
2006-11-22

BEREKENINGEN
Het is mogelijk om direct in de query berekeningen uit te voeren met waarden.
Je kunt daarbij optellen ( + ), aftrekken ( - ), delen ( / ) en vermenigvuldigen ( * )

Stel dat je bij de scores van sommige leden 100 wilt optellen, en wel die leden waarbij de score kleiner is dan 100 maal de leeftijd, dan kan dat met de volgende query:

SELECT score + 100 AS score_plus_100 FROM leden WHERE (leeftijd * 100 > score) ;

Dit geeft als resultaat:
naamscore_plus_10
Gerrit6089
Dieuwke7445
Kees6445
Sabine5099
Femke3868

Overzicht van de sql-functies

  • COUNT(kolomnaam) : geeft het aantal rijen in de tabel. Ook kan count(*) en count(nummer van de kolom)
  • MIN(kolom) : geeft het kleinste getal bij een numerieke kolom, of bij een tekstuele kolom de string die alfabetisch het eerst komt, of bij een datum-kolom de vroegste datum.
  • MAX(kolom) : geeft het grootste getal bij een numerieke kolom, of bij een tekstuele kolom de string die alfabetisch het laatst komt, of bij een datum-kolom de laatste datum.
  • SUM(kolom) : geeft de som van alle waarden uit de kolom, dat kan alleen bij numerieke kolommen.
  • AVG(kolom) : geeft het gemiddelde van een kolom, dat kan alleen bij numerieke kolommen.
  • ROUND(kolom, aantal decimalen): zorgt ervoor dat de getallen in de betreffende kolom worden afgerond op het aantal decimalen dat je hebt opgegeven.
  • LCASE(kolomnaam) : geeft de tekst in de kolom in kleine letters.
  • CONCAT(kolom1,kolom2 ) : plakt de twee kolommen achter elkaar, er kan ook een string aan worden vastgeplakt.
  • LEFT(kolom,n ) : geeft de eerste n tekens uit een kolom.
  • RIGHT(kolom,n ) : geeft de laatste n tekens uit een kolom.
  • INSTR(kolom, "karakter ") : geeft de eerste positie van een bepaald karakter in de kolom. Als het teken niet voorkomt in de string dan is het resultaat 0.
  • LEN(kolom) : geeft het aantal tekens van de woorden in de kolom. (in MySQL is het LENGTH( ) i.p.v. LEN( ) )
  • CURRENT_DATE( ) geeft de huidige systeemdatum als resultaat.
  • CURRENT_TIME( ) geeft de huidige systeemtijd als resultaat.
  • CURRENT_TIMESTAMP( ) geeft de huidige systeemdatum + systeemtijd als resultaat.
  • NOW( ) geeft ook de huidige systeemdatum + systeemtijd als resultaat.


Opgaven:
  1. Geef de query voor de gemiddelde leeftijd van de seniorleden.
  2. Geef de query voor het aantal aktieleden.
  3. Geef de query voor de leeftijd van het oudste lid.
  4. Geef de query voor de geboortedatum van het jongste lid uit Buitenpost.
Je kunt de queries hier uitproberen. Voer de query hieronder in, dan wordt hij door MySQL verwerkt.

Voer hier de query in: