Systematisch bouwen van informatiesystemen t.b.v. practicumopdracht : Relationele databases Structured Query Language SQL Relationele databases Geautomatiseerde informatiesystemen gebruiken bijna altijd een relationeel database management systeem RDBMS. De tabel is het centrale begrip in een relationele database. Een database in zo n RDBMS is een verzameling bij elkaar behorende gerelateerde tabellen. Binnen relationele databasesystemen is bijna altijd de taal SQL al dan niet volledig beschikbaar. Voorbeeld van een deel van een database voor een sportvereniging. Teams Boetes Spnr Spelernaam Straatnaam Plaatsnaam K. Huisman Spelers Annastraat 4 P.J. van Onderen Willemstraat 3 Teamnaam 4 P. van Oosterom Past. Pietstraat 4 Weurt W. De Bom Huilstraat 7 Wychen Boetenr 8 Datum F.G. Habank Spelersnr Vossendijk Bedrag 8 H. Flits Zwanenveld 8-0 Jeugd 0 L. Willemsen Kasteel 4 Wychen Jeugd Teamnaam Klasse /8/8 Aanvoerder.00 Broerdijk 3 /8/8 H. Nijboer Plein 44.00 Arnhem Jeugd 3 3/8/8 0 K. De Groot Huilstraat 00.00 3 Wychen Jeugd 0 B.E. Melmans Kasteel Wychen Jeugd Jeugd 3/8/8 0.00 3 W. De Bom Huilstraat 7 Wychen Jeugd /8/8 3 00.00 4 T. Huisman Annastraat 4 Jeugd 0/8/8.00 Snelweg 73 Lent 7 0/8/8 W.Jansen 4 Wolvendijk 3.00 Elst Jeugd 8 30 0/8/0 D. van Agt De Beurs.00 Groesbeek Jeugd 0 4 Spelers 3 //0 K. Zwartjes Past. Pietstraat.00 Weurt Jeugd 33 Eindhoven J. Mienen //0 Ekkersrijt 3.00 3//0 Ekkersrijt 3.00 Eindhoven Jeugd 3 D.F. Janssen Groenstraat 4 Oss 37 0//0 R. van der El Wolvendijk.00 Elst 40 0//0 G.E. Noeg Eindeweg 4.00 Tiel Jeugd Een tabel nader beschouwd kolomnaam Spelers Spnr Spelernaam Straatnaam Plaatsnaam Teamnaam K. Huisman Annastraat 4 P.J. van Onderen Willemstraat 3 P. van Oosterom Past. Pietstraat 4 Weurt 4 W. De Bom Huilstraat 7 Wychen 8 F.G. Habank Vossendijk 8 Jeugd H. Flits Zwanenveld 8-0 0 Jeugd L. Willemsen Kasteel 4 Wychen Broerdijk 3 H. Nijboer Plein 44 Arnhem Jeugd K. De Groot Huilstraat 3 Wychen 0 Jeugd B.E. Melmans Kasteel Wychen 3 Jeugd W. De Bom Huilstraat 7 Wychen 4 Jeugd T. Huisman Annastraat 4 Snelweg 73 Lent Jeugd W.Jansen Wolvendijk 3 Elst 30 Jeugd D. van Agt De Beurs Groesbeek 3 Jeugd K. Zwartjes Past. Pietstraat Weurt 33 J. Mienen Ekkersrijt 3 Eindhoven Jeugd Ekkersrijt Eindhoven 3 D.F. Janssen Groenstraat 4 Oss 37 R. van der El Wolvendijk Elst 40 Jeugd G.E. Noeg Eindeweg 4 Tiel 4 Jeugd R. Heymans Dreef 4 Grave 44 Jeugd P. van Oss Dreef 4 Oss regel 4 44 R. Heymans Dreef 4 Grave P. van Oss Dreef 4 Oss Jeugd 3 Jeugd Spnr = Spelersnr kolom 4 De overige tabellen: Boetes Boetenr Datum Spelersnr Bedrag 3 4 7 8 0 4 /8/0 /8/0 3/8/0 3/8/0 /8/0 0/8/0 0/8/0 0/8/0 //0 //0 3//0 0//0 0//0 4.00.00 00.00.00 00.00.00.00.00.00.00 3.00.00.00 Teams Teamnaam Klasse Aanvoerder Jeugd 0 Jeugd 3 0 3 Trainers Teamnaam Spelersnr Jeugd Jeugd Jeugd Jeugd Jeugd 3 3 Waarom niet alle data in één grote tabel plaatsen? Zoals bij de combinatie van Spelers en Teams: Redenen: Redundantie update probleem Vereist meer ruimte '.! "! #,! *0% *" # - 0!.!!",- #,! *" # "./" -,% *! "" # "" "" "" ""' 7! % /. ",!% "". " ""' "" 3' #!%, "" "" %% " %% "! "" #!% #" + " "! 0% #" +! +! " RU, voorjaar 00
SQL : Structured Query Language SQL is vooral een opvraagtaal via Daarnaast kent de taal elementen waarmee o.a.: de structuur van de tabellen in de gegevenbank kan worden vastgelegd en gewijzigd; CREATE en ALTER gegevens aan de tabellen kunnen worden toegevoegd INSERT gegevens in de tabellen kunnen worden gewijzigd gegevens uit de tabellen kunnen worden verwijderd UPDATE DELETE Kortom: de vier belangrijke operaties op databases zijn ermee mogelijk! 7 SQL--sjabloon voor nìet-gegroepeerde! gegevens: < wat je wilt zien > < te gebruiken tabellen > WHERE < in acht te nemen regelvoorwaarden > ORDER BY < gewenst sorteer-criterium > Bijvoorbeeld: spelernaam, straatnaam, WHERE teamnaam = '' ORDER BY 8 SQL WHERE - operatoren Met WHERE -operatoren geef je aan, aan welke speciale of gecombineerde voorwaarden de te gebruiken gegevensregels moeten voldoen. Veel gebruikte WHERE-operatoren zijn: - een aantal BOOLEAN operatoren, zoals: AND / OR / NOT / = / > / < / <> / >= / IS NOT NULL NULL: niet-ingevulde waarde én: - IN... zit iets IN een verzameling waarden? - BETWEEN... AND... zit tussen deze waarden? inclusief grenzen - LIKE... voldoet iets aan een bepaald patroon? ; met % en _ N.B. in MS Access zijn deze wild cards : * en? Bijvoorbeeld: WHERE-operatoren WHERE spelernaam NOT LIKE '%Jans%' AND IN '', 'Arnhem', 'Eindhoven' OR teamnaam = '' N.B. Let op eventueel benodigde haakjes! bijv. van welke spelers/ speelsters krijg je met deze query de gegevens te zien? N.B. in MS Access moet dat LIKE -deel dus zijn: NOT LIKE '*Jans*' SPELERSNR 8 3 4 33 3 SPELERNAAM K. Huisman P.J. van Onderen F.G. Habank H. Flits H. Nijboer T. Huisman J. Mienen D.F. Janssen STRAATNAAM Annastraat 4 Willemstraat 3 Vossendijk 8 Zwanenveld 8-0 Broerdijk Plein 44 Annastraat 4 Snelweg 73 Ekkersrijt 3 Ekkersrijt 3 Groenestraat 4 PLAATSNAAM Arnhem Lent Eindhoven Eindhoven Oss TEAMNAAM Jeugd Jeugd Jeugd 0 SQL - operatoren en functies Voor het tonen van tabelgegevens of daarvan afgeleide waarden Standaard: - DISTINCT versus het default ALL - COUNT voor het tellen van een aantal keren - SUM voor het optellen van numerieke waarden - MIN => minumumwaarde - MAX => maximumwaarde - AVG AVG: AVeraGe ; gemiddelde waarde Bijvoorbeeld: MAX bedrag, SUM bedrag, COUNT * WHERE bedrag >= OR spelersnr = Een paar dingen die NIET mogen... De statistische functies werken op kolomgegevens; MAX is wel toegestaan => Wychen! maar MAXCOUNT* is dus niet toegestaan! In queries nog zonder groeperen zie later, mag je in de regel òf alleen kolomnamen, òf alleen statistische functies gebruiken; een mix daarvan is niet toegestaan! Dus wèl mag bijvoorbeeld: COUNT*, MAX bedrag, AVG bedrag Boetes WHERE spelersnr = Maar niet: datum, MAX bedrag, AVG bedrag Boetes N.B. dit wordt anders bij groeperen! N.B. let bij WHERE-tests op vergelijking met numerieke of string -waarden => met versus zonder enkele of dubbele aanhalingstekens/apostrophes! RU, voorjaar 00
De - operator DISTINCT DISTINCT spelersnr boetes Spelersnr Spelersnr Spelersnr De DISTINCT-operator 'zeeft' als het ware de duplicaten uit: 4 oorspronkelijk 4 4 3 DISTINCT-operatie resultaat Ordenen sorteren met ORDER BY Voorbeeld: De penningmeester wil de gegevens uit de boetes-tabel in volgorde van het spelersnr op het scherm zien. ORDER BY spelersnr N.B. Voor sorteren van-hoog-naar-laag geef je de DESC descending optie mee. Default: ASC van ascending Ook sorteren op meerdere criteria tegelijk is mogelijk: WHERE bedrag >.00 ORDER BY bedrag, spelersnr DESC N.B. De ORDER BY-regel komt altijd achteraan! 4 Gegevensvragen met groepering Spnr Spelernaam Straatnaam Plaatsnaam Teamnaam groeps nummer Ter voorbereiding!: 3 H. Nijboer Plein 44 Arnhem Groeperen van gegevens ORDER BY 33 J. Mienen Ekkersrijt 3 Eindhoven Ekkersrijt Eindhoven Jeugd W.Jansen Wolvendijk 3 Elst Jeugd 37 R. van der El Wolvendijk Elst 4 R. Heymans Dreef 4 Grave Jeugd 30 D. van Agt De Beurs Groesbeek Jeugd Snelweg 73 Lent K. Huisman Annastraat 4 3 4 P.J. van Onderen Willemstraat 3 8 F.G. Habank Vossendijk 8 H. Flits Zwanenveld 8-0 Jeugd 7 Broerdijk 4 T. Huisman Annastraat 4 Jeugd 3 D.F. Janssen Groenstraat 4 Oss 44 P. van Oss Dreef 4 Oss Jeugd 8 40 G.E. Noeg Eindeweg 4 Tiel Jeugd Opmerking: De nummering van de groepen zie rechts is met de hand gedaan 4 P. van Oosterom Past. Pietstraat 4 Weurt 3 K. Zwartjes Past. Pietstraat Weurt Jeugd W. De Bom Huilstraat 7 Wychen 0 L. Willemsen Kasteel 4 Wychen Jeugd K. De Groot Huilstraat 3 Wychen Jeugd 0 B.E. Melmans Kasteel Wychen Jeugd 3 W. De Bom Huilstraat 7 Wychen Jeugd 0 Groepering via GROUP BY / HAVING Het GROUP BY commando heeft als effect dat functies die binnen de query voorkomen op iedere groep afzonderlijk worden toegepast Bijvoorbeeld: We willen het aantal spelers per plaats weten: GROUP BY, COUNT* spelers Resultaat: + +! "! 0% " #" 7 Groepering via GROUP BY / HAVING Opmerkingen: Alle losse kolomnamen die op de -regel voorkomen, moeten ook in de GROUP BY -regel voorkomen. Verder mogen in die eerste regel nog functies voorkomen die werken op zo'n "groep" rijen uit de gegevenstabel b.v. COUNT* of SUMbedrag etc.. Vraag: waar kun je in de boetes-tabel op groeperen en wat betekent dat? 8 RU, voorjaar 00 3
De HAVING -optie bij groeperen De HAVING-optie wordt gebruikt als we de gegevens van een groep alleen willen krijgen als die groep voldoet aan een bepaalde groepsvoorwaarde. Voorbeeld: we willen alleen die plaatsnamen met de bijbehorende spelersaantallen zien als er méér dan 4 spelers in de betreffende plaats wonen. De HAVING -optie bij groeperen Ander voorbeeld: spelersnr, COUNT * AS Aantal, SUM bedrag AS Som WHERE spelersnr <> GROUP BY spelersnr HAVING SUM bedrag > 0 Het SQL-commando:, COUNT * GROUP BY HAVING COUNT * > 4 + resultaat: Plaatsnaam COUNT* Wychen Resultaat: Vraag: wat is de achterliggende gegevensvraag bij deze query? 0 Gegevensvragen met groepering: sjabloon < wat je wilt zien > < te gebruiken tabellen > WHERE < in acht te nemen regelvoorwaarden > GROUP BY < groeperingswijze > HAVING < in acht te nemen groepsvoorwaarden > Ingewikkelder gegevensvragen ORDER BY < gewenst sorteer-criterium > Ingewikkelder gegevensvragen A => over méérdere tabellen: geneste gegevensvragen => subqueries samenvoegingen => joins Geneste gegevensvragen 3 groeperen van join-resultaten B => met extreme totaalwaardes >= ALL e.d. 3 4 RU, voorjaar 00 4
Geneste gegevensvragen met subqueries Geneste gegevensvragen met subqueries Een geneste gegevensvraag is een gegevensvraag, die zelf weer een andere gegevensvraag bevat. Voor het -commando betekent dit, dat in het WHERE-deel weer een ander, vervolg -commando staat. Voorbeeld : de subquery levert slechts één tussenresultaat => gebruik = spelernaam WHERE spelersnr = aanvoerder teams WHERE teamnaam = '' Voorbeeld : de subquery levert méérdere tussenresultaten => gebruik IN of beter: uit een analyse verwacht je dat de subquery meerdere resultaten zal of kan opleveren De informatievraag: Geef de namen en adressen van álle spelers die een boete moeten betalen die groter is dan,00. WHERE spelernaam, straatnaam, spelers spelersnr IN spelersnr WHERE bedrag >.00 Spelernaam #,! ""' Resultaat: Resultaat: *" 3' ",% %% " +! Samenvoeging van twee of meer tabellen joins => op de -regel komen meerdere tabelnamen te staan. Samenvoegen join van gegevenstabellen N.B. Gebruik daarbij steeds een of meer join-criteriums! Want als je dat niet doet, zoals bij: dan:, boetes verschijnt er onzin alle speler-regels worden met alle boete-regels gecombineerd 7 Als je vergeet join -criteria mee te nemen meestal onzin! spelers spelers. spelers. spelers. spelers. boetes. boetes. boetes. boetes. splnr spelernaam straatnaam teamnaam boetenr datum splrnr bedrag K. Huisman Annastraat 4 /8/0.00 K. Huisman Annastraat 4 /8/0.00 K. Huisman Annastraat 4 3 3/8/0 00.00 K. Huisman Annastraat 4 4 3/8/0.00 K. Huisman Annastraat 4 /8/0 00.00 K. Huisman Annastraat 4 0/8/0.00 K. Huisman Annastraat 4 7 0/8/0 4.00 K. Huisman Annastraat 4 8 0/8/0.00 K. Huisman Annastraat 4 //0.00 K. Huisman Annastraat 4 0 //0.00 K. Huisman Annastraat 4 3//0 3.00 K. Huisman Annastraat 4 4 0//0.00 K. Huisman Annastraat 4 0//0.00 P.J. van Onderen Willemstraat 3 /8/0.00 P.J. van Onderen Willemstraat 3 /8/0.00 P.J. van Onderen Willemstraat 3 3 3/8/0 00.00 44 P. van Oss Dreef 4 Oss Jeugd 3//0 3.00 44 P. van Oss Dreef 4 Oss Jeugd 4 0//0.00 44 P. van Oss Dreef 4 Oss Jeugd 0//0.00 Samenvoegcriterium alleen de zinvolle combinaties, boetes WHERE spelers.spelersnr = boetes.spelersnr Levert als zinvolle combinaties van tabelregels:!! " #,! ""' -,!% -,!% -,!% -,!% -,!% *" 3' " *" 3' " # #!% " # #!% ",% %% " +!,% %% " +! ' 30 RU, voorjaar 00
Werkbesparend: werken met aliassen SQL-join- syntax: ook een model... WHERE S.spelersnr, spelernaam, straatnaam,, bedrag spelers S, boetes B S.spelersnr = B.spelersnr tabelnaam. kolomnaam N.B. als je werkt met unieke kolomnamen, hoef je niet te verwijzen naar de tabel waar die kolom vandaan komt! spelersnr 4 spelernaam W. De Bom R. Heymans straatnaam Broerdijk Broerdijk Ekkersrijt 3 Wolvendijk 3 Huilstraat 7 Snelweg 73 Dreef 4 Broerdijk Broerdijk Broerdijk Snelweg 73 Ekkersrijt 3 Wolvendijk 3 Eindhoven Elst Wychen Lent Grave Lent Eindhoven Elst bedrag 00 00 3 3 WHERE, tabelnaam, samenvoegcriterium AND selectiecriterium 3 Combineren van join met groeperen Alleen samenvoegen Samenvoegen + groeperen Combineren van join met groeperen spelernaam, bedrag S, boetes B spelernaam bedrag 00 W. De Bom 00 R. Heymans spelernaam, SUM bedrag S, boetes B GROUP BY spelernaam spelernaam R. Heymans W. De Bom Som 0 0 8 00 30 3 33 Let op bij gebruik van kolomnamen in -regel Alle kolomnamen die in een -regel voorkomen, moeten óf in de GROUP BY-regel, óf in die -regel in een functie-vorm met SUM, MIN, etc. over een groep regels voorkomen. Níet mogelijk is dus een SQL-query als: Soms: verzin een list! spelernaam,, SUM bedrag S, boetes B GROUP BY spelernaam FOUT!! Indien de gegevensvraag echt is: Geef de naam, woonplaats en totaalboete van alle beboete spelers, dan zijn in dit geval de volgende truuks mogelijk, omdat hier elke speler toch maar in steeds één enkele plaats woont:, spelernaam, COUNT * GROUP BY FOUT!! Redenen: semantisch : wat zou dit moeten betekenen? Wat zou dan de achterliggende gegevensvraag moeten zijn? de SQL-syntax staat zo n mix niet toe! 3 a neem die in de -regel in een functievorm op: spelernaam, MAX, SUM bedrag S, boetes B GROUP BY spelernaam b neem die in de GROUP BY-regel op: spelernaam,, SUM bedrag S, boetes B GROUP BY spelernaam, GOED!! GOED!! 3 RU, voorjaar 00
Extreme totaalwaardes bij groeperen Extreme totaalwaardes bij groeperen 37 Bekijk eerst: bepaal per beboete speler het aantal boetes. spelersnr, COUNT* AS Aantal GROUP BY spelersnr spelersnr 4 Aantal Nu: geef het spelersnummer en het aantal boetes van de speler die het grootste aantal boetes heeft. spelersnr spelersnr, COUNT* AS Aantal GROUP BY spelersnr HAVING COUNT* >= ALL COUNT* GROUP BY spelersnr Aantal 38 Extreme totaalwaardes bij groeperen Informatievraag: geef de en het aantal daar wonende spelers van die plaats waar het kleinste aantal spelers woont., COUNT* AS Aantal GROUP BY HAVING COUNT* <= ALL COUNT* GROUP BY Joins versus subqueries Arnhem Grave Groesbeek Lent Tiel Aantal 3 40 Joins versus subqueries Vaak kan een informatievraag zowel via een join- als via een subqueryformulering worden beantwoord. Bijvoorbeeld: geef van de spelers die trainer zijn van een Jeugd-team, hun naam en hun woonplaats. spelernaam K. Huisman spelernaam, P.J. van Onderen WHERE spelersnr IN spelersnr trainers WHERE teamnaam LIKE "Jeugd%" of: gebruik DISTINCT...! spelernaam, S, trainers T WHERE S.spelersnr = T.spelersnr AND T.teamnaam LIKE "Jeugd%" spelernaam K. Huisman K. Huisman P.J. van Onderen P.J. van Onderen 4 Joins versus subqueries Je zult echter joins moeten gebruiken: indien je gegevens uit verschillende tabellen op eenzelfde regel wilt tonen Je zult echter subqueries moeten gebruiken: - indien je via bijv. >= ALL.. met minimum- of maximum-waarden te maken hebt; - i.h.a. bij [soms via functies] afgeleide condities bijv. WHERE spelersnr NOT IN spelersnr Probleempje bij MySQL... 4 RU, voorjaar 00 7
Practicumopdracht over SQL Zie Blackboard Er staat daar ook een MS Access -database-bestand gereed om te down loaden. Als je thuis geen MS Access kunt draaien, dan kun je bijv. terecht in een practicumzaal op de B-faculteit met een geldige login... Ik ga er vanuit, dat je zonder begeleiding van een studentassistent die opdracht kunt maken Bij vragen kun je me e-mailen Inlever dead line: vóór het volgende werkcollege van volgende week dinsdag; lever per groepje personen één uitwerking in! 43 RU, voorjaar 00 8