Relationele databases en SQL hoofdstuk 1 t/m 10 1
© Mattic b.v., Almere Alle rechten voorbehouden. Het is docenten toegestaan deze diaserie te gebruiken in combinatie met het cursusboek. Hierbij mogen ook handouts worden verspreid. Het ppt-bestand bevat voor de SQL-code een niet-standaardlettertype (Letter Gothic). Wanneer u dit niet op uw computer hebt staan, moet u de bestanden openen met het kenmerk alleen-lezen. Anders wordt het lettertype verwijderd, wat ten koste gaat van de opmaak. Zie ook: Informatie over codelettertype voor Windows- en Mac-gebruikers.doc.
bij: Relationele databases en SQL ©Mattic b.v. Cursusmateriaal cursusboek: Relationele databases en SQL downloaden van www.relsql.nl: installatiefile voor de software: Firebird: databasemanagementsysteem Boekverkenner: interactieve versie van het boek IQU (Interactive Query Utility): SQL-tool uitwerkingen van opgaven (pdf) errata Installatie van de software: executeer de installatiefile, accepteer alle defaults bij: Relationele databases en SQL ©Mattic b.v. 3
bij: Relationele databases en SQL ©Mattic b.v. Inhoud boek (1) Deel A: Relationele databases 1 Relationele databases: structuur relationele model en normalisatie, practisch ... 2 Relationele databases: regels 3 Communiceren met een relationele database ‘applicatie’ praat via SQL met database 4 Nulls … en theoretisch 5 Normalisatie bij: Relationele databases en SQL ©Mattic b.v. 4
bij: Relationele databases en SQL ©Mattic b.v. Inhoud boek (2) Deel B: Relationele databases bevragen en wijzigen 6 Informatie uit één tabel 7 Informatie uit meerdere tabellen: joins subtaal SQL-DML (Data Manipulation Language) 8 Statistische informatie 9 Subselects en views 10 Wijzigen van een database-inhoud bij: Relationele databases en SQL ©Mattic b.v. 5
bij: Relationele databases en SQL ©Mattic b.v. Inhoud boek (3) Deel C: Relationele databases beheren 11 Definitie van gegevensstructuren SQL-DDL 12 Autorisatie rechten voor gebruikers 13 Query-optimalisatie bij grote databases Deel D: Verdieping 14 Aanpak van queryproblemen methodisch problemen oplossen 15 Transacties en concurrency meer gebruikers 16 Triggers en stored procedures programmeren van regels 17 De datadictionary het hart van een relationeel systeem bij: Relationele databases en SQL ©Mattic b.v. 6
Relationele databases: structuur Hoofdstuk 1: Relationele databases: structuur 7
bij: Relationele databases en SQL ©Mattic b.v. In dit hoofdstuk …. Een applicatie die gebruikmaakt van een relationele database Structuren: van gegevens in de applicatie en van gegevens in de database Je moet ongewenste databasestructuren kunnen herkennen en tranformeren: herhalende groepen redundantie (overtolligheid van gegevens) Standaardisatie In deze cursus: nog geen databases ontwerpen! bij: Relationele databases en SQL ©Mattic b.v. 8
Applicatie: Toetjesboek (applicatie bij Firebird-database) bij: Relationele databases en SQL ©Mattic b.v. 9
Toetjesboek (applicatie) Functionaliteit = wat ‘doet’ de applicatie? Functionaliteit van Toetjesboek: ‘onderhoud’ van gerechten, hun ingrediënten, producten en eenheden invoegen (insert) verwijderen (delete) wijzigen (update) zoeken en bladeren bij: Relationele databases en SQL ©Mattic b.v. 10
Receptwindow in applicatie (schematisch) bij: Relationele databases en SQL ©Mattic b.v. 11
Hoe de gegevens opslaan in database? (1) Alle gegevens van alle gerechten in één tabel? Bezwaren: ‘redundantie’ structuur is (onnodig) complex: de vijfde kolom heeft een samengestelde structuur (subtabel in elke rij) bij: Relationele databases en SQL ©Mattic b.v. 12
bij: Relationele databases en SQL ©Mattic b.v. Redundantie (1) Redundantie = reconstrueerbaarheid van gegeven(s) uit de context Ofwel: ‘uit kunnen gummen’ en weer terug kunnen vinden! NB. Je moet wel weten dat er per product maar één eenheid is: beschouw dit als gegeven. bij: Relationele databases en SQL ©Mattic b.v. 13
bij: Relationele databases en SQL ©Mattic b.v. Redundantie (2) Redundantie kan tot inconsistentie leiden: Inconsistentie = tegenstrijdigheid van gegeven(s) Beter op één plek verkeerd dan half goed, half fout ! bij: Relationele databases en SQL ©Mattic b.v. 14
bij: Relationele databases en SQL ©Mattic b.v. Herhalende groep Bezwaren: ingewikkelder databasebeheer gebrek aan symmetrie in behandeling van ‘soorten van dingen’ Opslagstructuur hoort ‘neutraal’ te zijn (i.t.t. een applicatie, die taakgericht is) bij: Relationele databases en SQL ©Mattic b.v. 15
‘Omkering’ van herhalende groep ‘gerechten’ als herhalende groep bij producten! bij: Relationele databases en SQL ©Mattic b.v. 16
Elimineren herhalende groep bij: Relationele databases en SQL ©Mattic b.v.
Elimineren redundantie: ‘SPOD’ Single Point Of Definition: alle informatie op één plaats gedefinieerd elk ‘soort van ding’ zijn eigen tabel bij: Relationele databases en SQL ©Mattic b.v. 18
bij: Relationele databases en SQL ©Mattic b.v. Standaardisatie Ook eenheden zijn dingen van zelfstandig belang: standaardisatie gewenst ! bij: Relationele databases en SQL ©Mattic b.v. 19
Genormaliseerde relationele database relatie = ‘tabel’ relationele database = database bestaande uit tabellen ‘volledig genormaliseerd’: - geen herhalende groepen - geen redundantie normalisatie garandeert niet altijd standaardisatie ! tabel Eenheid ! bij: Relationele databases en SQL ©Mattic b.v. 20
Databasestructuur: strokendiagram bij: Relationele databases en SQL ©Mattic b.v. 21
‘Tabel’ versus ‘relatie’ ‘tabel’ in de zin van ‘relatie’: volgorde rijen en van kolommen niet van belang er zijn géén gelijke rijen, ook al noteer je ze meervoudig bij: Relationele databases en SQL ©Mattic b.v. 22
Informatie als verwoording van gegevens vier ‘informatie- atomen’: Atomaire informatie bij: Relationele databases en SQL ©Mattic b.v. 23
Relationele databases: regels Hoofdstuk 2: Relationele databases: regels 24
bij: Relationele databases en SQL ©Mattic b.v. In dit hoofdstuk …. Optionele kolommen Uniciteitsregels Sleutels De referentiële integriteitsregel Refererende actieregels Transacties Recursieve verwijzingen bij: Relationele databases en SQL ©Mattic b.v. 25
bij: Relationele databases en SQL ©Mattic b.v. Optionele kolommen (1) nulls Een null: speciaal soort waarde (indicator dat geen gewone waarde is ingevuld) Optionele kolom mag nulls bevatten. bij: Relationele databases en SQL ©Mattic b.v. 26
bij: Relationele databases en SQL ©Mattic b.v. Optionele kolommen (2) afleidbare kolom Optionele kolom in strokendiagram: o bij: Relationele databases en SQL ©Mattic b.v. 27
bij: Relationele databases en SQL ©Mattic b.v. Uniciteitsregels (1) overtredingen van uniciteits- regel Coupe Kiwano .. .. .. Coupe Kiwano .. .. .. … .. .. .. Coupe Kiwano ijs .. .. .. .. .. .. Onder uniciteitspijl is meervoudig voorkomende waarden (waardencombinatie) niet toegestaan. bij: Relationele databases en SQL ©Mattic b.v. 28
bij: Relationele databases en SQL ©Mattic b.v. Uniciteitsregels (2) Een uniciteitspijl kan nooit ‘binnen’ een bredere uniciteitspijl zitten: alleen de meest strenge regel wordt genoteerd. bij: Relationele databases en SQL ©Mattic b.v. 29
Illustratieve populatie Een illustratieve populatie voldoet aan alle regels, maar illustreert ook wat is toegestaan. De populatie hierboven illustreert bv. dat voor de afzonderlijke kolommen gerecht en product géén uniciteitsregel geldt. bij: Relationele databases en SQL ©Mattic b.v. 30
bij: Relationele databases en SQL ©Mattic b.v. Sleutels primaire sleutel = kolom of kolomcombinatie waarvoor geldt: 1. verplicht; 2. met (meest strenge) uniciteitsregel; 3. aangewezen als logisch adres van een rij voor verwijzingen naar die rij verwijssleutel = kolom (of kolomcombinatie) waarvan waarden (of waardencombinaties) verwijzen naar andere rijen (via de primaire sleutel daarvan) bij: Relationele databases en SQL ©Mattic b.v. 31
bij: Relationele databases en SQL ©Mattic b.v. Primaire ‘sloten’ ? bij: Relationele databases en SQL ©Mattic b.v. 32
Referentiële integriteitsregel Referentiële integriteitsregel: Elke waarde van een verwijzende sleutel moet voorkomen als waarde van de bijbehorende primaire sleutel. Dus: Als in kindtabel een verwijzende waarde is ingevuld, moet die waarde voorkomen in de oudertabel (als waarde van de primaire sleutel). bij: Relationele databases en SQL ©Mattic b.v. 33
Cardinaliteitsregels Je leest de cardinaliteit aan de andere kant van het lijntje ! bij: Relationele databases en SQL ©Mattic b.v. 34
(Groot)ouder-(klein)kind bij: Relationele databases en SQL ©Mattic b.v. 35
Ouder-kind: relatief t.o.v. verwijzing Tekenconventie: ouder boven, kind onder, indien mogelijk bij: Relationele databases en SQL ©Mattic b.v. 36
bij: Relationele databases en SQL ©Mattic b.v. Kunstmatige sleutels Kunstmatige sleutels: - meestal numeriek (daarmee kun je snel zoeken en sorteren) - vaak alleen in database, niet zichtbaar in eindgebruikersapplicatie. bij: Relationele databases en SQL ©Mattic b.v.
Alternatieve sleutels primaire sleutel alternatieve sleutel bij: Relationele databases en SQL ©Mattic b.v. 38
Kandidaatsleutels en supersleutel kandidaatsleutel = kolom of kolomcombinatie waarvoor geldt: 1. verplicht 2. met (zo zuinig mogelijke) uniciteitsregel. Als er meerdere kandidaatsleutels zijn wordt één ervan gekozen als primaire sleutel. De andere is (of zijn) dan per definitie een alternatieve sleutel. supersleutel = kandidaatsleutel of omvattende kolomcombinatie bij: Relationele databases en SQL ©Mattic b.v. 39
Refererende actieregels De refererende actieregels moeten zorgen dat de referentiële integriteitsregel blijft gelden wanneer je een rij verwijdert, of wanneer je een primaire-sleutelwaarde wijzigt: Voor een verwijzing geldt altijd één van de delete-regels: restricted delete cascading delete nullifying delete … en één van de update-regels: restricted update cascading update nullifying update bij: Relationele databases en SQL ©Mattic b.v. 40
bij: Relationele databases en SQL ©Mattic b.v. Restricted delete bij: Relationele databases en SQL ©Mattic b.v. 41
bij: Relationele databases en SQL ©Mattic b.v. Transacties Commit: opdracht om opdrachten definitief uit te voeren. Rollback: opdracht om opdrachten ongedaan te maken. Transactie: reeks opdrachten die als geheel worden uitgevoerd (of in hun geheel ongedaan worden gemaakt). Na een succesvolle transactie is aan alle databaseregels voldaan! Ofwel: de database is dan integer. vindt vaak automatisch plaats bij: Relationele databases en SQL ©Mattic b.v. 42
bij: Relationele databases en SQL ©Mattic b.v. Cascading delete bij: Relationele databases en SQL ©Mattic b.v. 43
bij: Relationele databases en SQL ©Mattic b.v. Cascading update bij: Relationele databases en SQL ©Mattic b.v. 44
Update- en deleteregels in Toetjesboek-database bij: Relationele databases en SQL ©Mattic b.v. 45
Samengestelde sleutel bij: Relationele databases en SQL ©Mattic b.v. 46
Recursieve verwijzing bij: Relationele databases en SQL ©Mattic b.v. 47
Veel-veel associatie van tabel met zichzelf veel-veel associatie tussen tabel Cursus en zichzelf: “cursus … eist als voorkennis cursus …” bij: Relationele databases en SQL ©Mattic b.v. 48
Veel-veel associatie van tabel met andere tabel veel-veel associatie tussen tabellen Docent en Cursus: “docent … is begeleider van cursus …” bij: Relationele databases en SQL ©Mattic b.v. 49
Niet-sleutelverwijzing bij: Relationele databases en SQL ©Mattic b.v. 50
De OpenSchool-database bij: Relationele databases en SQL ©Mattic b.v. 51
Communiceren met een relationele databases Hoofdstuk 3: Communiceren met een relationele databases 52
bij: Relationele databases en SQL ©Mattic b.v. In dit hoofdstuk …. applicatie en database: Toetjesboek SQL select-query’s select-query’s op meer dan één tabel: joins tabelinhouden wijzigen: insert-, delete- en update-query’s demonstratie Boekverkenner, SQL-tool en applicatie bij: Relationele databases en SQL ©Mattic b.v. 53
Nogmaals: Toetjesboek (eindgebruikersapplicatie) bij: Relationele databases en SQL ©Mattic b.v. 54
bij: Relationele databases en SQL ©Mattic b.v. Toetjesboek: vragen Welke gegevens zijn berekenbaar uit andere gegevens? Welke gegevens moeten worden opgeslagen? Zijn daar ook gegevens bij die niet zichtbaar zijn in het Gerechten-venster? Zijn er gegevens die zeker niet worden opgeslagen? Voor welke gegevens is keuze mogelijk? Wat zijn de consequenties van die keuze? bij: Relationele databases en SQL ©Mattic b.v. 55
bij: Relationele databases en SQL ©Mattic b.v. 56
bij: Relationele databases en SQL ©Mattic b.v. Een SQL-select query select naam, energiePP -- 3 from Gerecht -- 1 where bereidingstijd < 30 -- 2 order by energiePP -- 4 Ga uit van tabel Gerecht: alle rijen Verwijder de rijen die niet aan de conditie voldoen Geef voor elke rij die nog over is: gerechtnaam en energiePP Orden de rijen op volgorde van energiePP bij: Relationele databases en SQL ©Mattic b.v. 57
Selectquery op meer dan één tabel: join join van Ingredient en Product: verbreding van Ingredient met de niet-sleutelkolommen van Product, via de verwijssleutel bij: Relationele databases en SQL ©Mattic b.v. 58
bij: Relationele databases en SQL ©Mattic b.v. De join in SQL alle kolommen van de combinatie, behalve de primaire sleutel van Product Joinquery in SQL: select Ingredient.gerecht, Ingredient.product, Ingredient.hoeveelheidPP, Ingredient.volgnr, Product.eenheid, Product.energiePE from Ingredient join Product on Ingredient.product = Product.naam alle rijen van Ingredient gecombineerd met alle bijbehorende rijen van Product, via de verwijssleutel Korter, met ‘tabelaliassen’: select I.gerecht, I.product, I.hoeveelheidPP, I.volgnr, P.eenheid, P.energiePE from Ingredient I join Product P on I.product = P.naam bij: Relationele databases en SQL ©Mattic b.v. 59
Tabelinhouden wijzigen Wijzigen van een tabelinhoud: toevoegen van een rij (insert) verwijderen van een rij (delete) wijzigen van een bestaande rij (update) bij: Relationele databases en SQL ©Mattic b.v. 60
bij: Relationele databases en SQL ©Mattic b.v. Insert Voorbeeld: voeg het product ‘goudrenetten’ toe, gemeten in pond en met een energiewaarde van 330 kcal per pond. Oplossing: insert into Eenheid values ('pond'); insert into Product values ('goudrenetten', 'pond', 330) Ga na: zonder de eerste opdracht krijg je een foutmelding (overtreding van de referentiële integriteitsregel) bij: Relationele databases en SQL ©Mattic b.v. 61
bij: Relationele databases en SQL ©Mattic b.v. Delete Voorbeeld: verwijder het gerecht ‘banaan’. Oplossing: delete -- 3 from Product -- 1 where naam = ‘banaan’ -- 2 Opgaven Voorspel wat er gebeurt bij een poging het product ‘mango’ te verwijderen. Voorspel wat er gebeurt bij een poging het gerecht ‘Mango Plus Plus’ te verwijderen. Zie ook de populatie, in boek of de Voorbeeldverkenner bij: Relationele databases en SQL ©Mattic b.v. 62
bij: Relationele databases en SQL ©Mattic b.v. Update Voorbeeld: wijzig de energie per eenheid van goudrenetten in 550. Oplossing: update Product -- 1 set energiePE = 550 -- 3 where naam = 'goudrenetten' -- 2 toekenning test op gelijkheid (resultaat ‘waar’ of ‘onwaar’) Opgave Voorspel wat er gebeurt bij een poging om in tabel Gerecht de naam ‘Coupe Kiwano’ te wijzigen in ‘Coupe Reijnders’. bij: Relationele databases en SQL ©Mattic b.v. 63
bij: Relationele databases en SQL ©Mattic b.v. Triggers en scripts Waarden van Gerecht.energiePP worden automatisch berekend via triggers. Triggers zijn kleine programma’s die kunnen worden gekoppeld aan een insert, delete of update (of een poging daartoe) Opgaven Raadpleeg het create-script van Toetjesboek en zoek de create trigger-opdrachten. Probeer het script globaal te begrijpen. Raadpleeg het insert-script van Toetjesboek en probeer dit globaal te begrijpen. Inserts, deletes en updates worden in detail behandeld in hoofdstuk 10. Triggers worden behandeld in hoofdstuk 16. bij: Relationele databases en SQL ©Mattic b.v. 64
Demonstratie Boekverkenner, SQL-tool en applicatie Toetjesboek-applicatie doet het niet zonder geïnstalleerde Toetjesboek-database! Toetjesboek-database installeren via Boekverkenner Toetjesboek-applicatie verkennen let op SQL-verkeer van en naar de SQL-server! Interactive Query Utility (IQU) SQL-query vanuit IQU Boekverkenner dababases installeren en de-installeren inloggen op database navigeren door de boektekst SQL-query uitvoeren vanuit de boektekst de Voorbeeldnavigator bij: Relationele databases en SQL ©Mattic b.v.
Hoofdstuk 4: Nulls 66
bij: Relationele databases en SQL ©Mattic b.v. In dit hoofdstuk …. de aard van nulls nulls en de lege string Codd-relationaliteit logische algebra: twee- en driewaardige logica bij: Relationele databases en SQL ©Mattic b.v. 67
De OpenSchool-database bij: Relationele databases en SQL ©Mattic b.v. 68
bij: Relationele databases en SQL ©Mattic b.v. De aard van nulls Null: speciale waarde indicator voor niet-ingevulde ‘echte’ waarde bij: Relationele databases en SQL ©Mattic b.v. 69
bij: Relationele databases en SQL ©Mattic b.v. Rekenen met null Optellen met null-operand select cijfer + 1 from Inschrijving Resultaat: ADD ============== 8 6 9 <NULL> bij: Relationele databases en SQL ©Mattic b.v. 70
Null en de lege string (1) lege string (= string van lengte 0): is dat een null? blijkt afhankelijk van de database (bv. Oracle of Firebird) bij: Relationele databases en SQL ©Mattic b.v. 71
Null en de lege string (2) een lege string in Firebird is géén null! vergelijk gedrag bij concatenatie: bij: Relationele databases en SQL ©Mattic b.v. 72
bij: Relationele databases en SQL ©Mattic b.v. Selecteren op null Inschrijvingen waarvoor geen cijfer is ingevuld: select * from Inschrijving where cijfer is null Inschrijvingen waarvoor wel een cijfer is ingevuld: where cijfer is not null of: not(cijfer is null) bij: Relationele databases en SQL ©Mattic b.v. 73
Codd-relationaliteit In een Codd-relationele database is elke kolom van een primaire sleutel verplicht. Voorbeeld niet-Codd-relationele tabel: bij: Relationele databases en SQL ©Mattic b.v. 74
bij: Relationele databases en SQL ©Mattic b.v. Logische algebra logische algebra: ‘rekenen’ met logische waarden logische waarden: in tweewaardige logica: true en false in tweewaardige logica: true, false en unknown voorbeelden van logische expressies: 1+1 = 2 levert true 1+1 = 1 levert false 1+null = 1 levert unknown NB. where unknown heeft hetzelfde effect als where false! bij: Relationele databases en SQL ©Mattic b.v. 75
bij: Relationele databases en SQL ©Mattic b.v. Opgave Voorspel het effect van: a) b) c) select * from Inschrijving where cijfer is null select * from Inschrijving where cijfer = null select * from Inschrijving where null = null bij: Relationele databases en SQL ©Mattic b.v. 76
bij: Relationele databases en SQL ©Mattic b.v. Tweewaardige logica operatoren: not, and en or rekenregels: NB: or = ‘en/of’ bij: Relationele databases en SQL ©Mattic b.v. 77
Prioriteit operatoren 1. not 2. and 3. or Vergelijk: en: select student, cursus, cijfer, vrijstelling from Inschrijving where not(vrijstelling = 'J' or cijfer > 5) select student, cursus, cijfer, vrijstelling from Inschrijving where not vrijstelling = 'J' or cijfer > 5 bij: Relationele databases en SQL ©Mattic b.v. 78
bij: Relationele databases en SQL ©Mattic b.v. Regels van De Morgan Voorbeeld 1e regel: is equivalent met: Vraag: welke haakjes mogen weg? select student, cursus, cijfer, vrijstelling from Inschrijving where not(vrijstelling = 'J' or cijfer > 5) select student, cursus, cijfer, vrijstelling from Inschrijving where not(vrijstelling) = 'J‘) and not(cijfer > 5) bij: Relationele databases en SQL ©Mattic b.v. 79
bij: Relationele databases en SQL ©Mattic b.v. Driewaardige logica rekenregels: waarom? zijn deze regels aannemelijk te maken? bij: Relationele databases en SQL ©Mattic b.v. 80
bij: Relationele databases en SQL ©Mattic b.v. Voorbeeld Select-query: geeft als resultaat alle inschrijvingen met vrijstelling = ‘J’ (ongeacht het cijfer en of dat is ingevuld) en alle inschrijvingen met cijfer > 5 (ongeacht de waarde van vrijstelling en of die is ingevuld) select student, cursus, cijfer, vrijstelling from Inschrijving where vrijstelling = 'J' or not cijfer <= 5 bij: Relationele databases en SQL ©Mattic b.v. 81
Hoofdstuk 5: Normalisatie 82
bij: Relationele databases en SQL ©Mattic b.v. In dit hoofdstuk …. normaalvormen herhalende groepen en de eerste normaalvorm (1NV) functionele afhankelijkheid en de tweede en derde normaalvormen (2NV en 3NV) de Boyce-Codd-normaalvorm nabeschouwing: wat is normaliseren en wat is het niet? voor liefhebbers: 4NV en 5NV op relsql.nl bij: Relationele databases en SQL ©Mattic b.v. 83
bij: Relationele databases en SQL ©Mattic b.v. Normaalvormen Een normaalvorm is een bepaalde gewenste tabelstructuur, waarin een (door die normaalvorm verboden) situatie niet optreedt. eerste normaalvorm (1NV) verbod op herhalende groepen tweede en derde normaalvorm (2NV en 3NV) verbod op bepaalde vormen van redundantie (overtolligheid van gegevens) Boyce-Codd-normaalvorm verbiedt nog net wat meer dan 3NV (maar is wat problematisch …) Deze normaalvormen worden steeds strenger: er wordt steeds wat meer verboden bij: Relationele databases en SQL ©Mattic b.v. 84
Niet-genormaliseerde tabel een tabel met drie kolommen: derde kolom is gestructureerd (herhalende groep) de herhalende groep heeft in elke cel een (deel)tabel 1NV verbiedt herhalende groepen (niet-relationeel!) niet-genormaliseerd = niet-1NV ! (R=regulier; T= tentamenstudent) bij: Relationele databases en SQL ©Mattic b.v. 85
Van niet-genormaliseerd naar 1NV (1) ‘afsplitsen’ herhalende groep bij: Relationele databases en SQL ©Mattic b.v. 86
Functionele afhankelijkheid (FA) als je de cursus weet, weet je het aantal studiepunten: Synoniemen: cursus determineert studiepunten studiepunten wordt gedetermineerd door cursus studiepunten is functioneel afhankelijk van cursus bij: Relationele databases en SQL ©Mattic b.v. 87
bij: Relationele databases en SQL ©Mattic b.v. Nog een FA tarief is functioneel afhankelijk van inschrijvingstype Dit spreekt niet vanzelf: je moet hiervoor weten dat het tarief niet óók afhankelijk is van de cursus! Dit moet dus gegeven zijn, een voorbeeldpopulatie is niet voldoende (waarom niet?) bij: Relationele databases en SQL ©Mattic b.v. 88
bij: Relationele databases en SQL ©Mattic b.v. Triviale FA’s (1) Alle kolommen zijn functioneel afhankelijk van de primaire sleutel! Waarom? bij: Relationele databases en SQL ©Mattic b.v. 89
bij: Relationele databases en SQL ©Mattic b.v. Triviale FA’s (2) Elke kolom(combinatie) is functioneel afhankelijk van zichzelf Elke combinatie is functioneel afhankelijk van een combinatie waar hij deel van uitmaakt Triviale functionele afhankelijkheden zijn niet interessant! bij: Relationele databases en SQL ©Mattic b.v. 90
Redundantie door niet-triviale FA’s Niet de FA’s zijn de boosdoener (die zijn ze zoals ze zijn), maar de structuur. We transformeren de structuur, zó dat de FA’s triviaal worden. bij: Relationele databases en SQL ©Mattic b.v. 91
Overtredingen van 2NV en 3NV bij: Relationele databases en SQL ©Mattic b.v. 92
Transformatie: van niet-2NV naar 2NV situatie verboden door 2NV (uitgaande van 1NV): A, B, C, …: kolommen of kolomcombinaties transformatie naar 2NV: ‘afsplitsen van FA’ NB. De FA is er nog steeds, maar nu als triviale FA in de (nieuwe) oudertabel. Je zou kunnen zeggen: ‘de FA heeft een eigen tabel gekregen’. bij: Relationele databases en SQL ©Mattic b.v. 93
Toegepast op voorbeeld 1NV / niet-2NV na afsplitsen FA: 2NV bij: Relationele databases en SQL ©Mattic b.v. 94
Transformatie: van 2NV/niet-3NV naar 3NV bij: Relationele databases en SQL ©Mattic b.v. 95
Toegepast op voorbeeld 2NV / niet-3NV na afsplitsen FA: 3NV geen redundantie meer! bij: Relationele databases en SQL ©Mattic b.v. 96
Wat wordt verboden door BCNV ? Verboden situatie (uitgaande van 1NV): (niet uniek) De Boyce-Codd normaalvorm verbiedt alle niet-triviale functionele afhankelijkheden met niet-unieke determinant. Dit is een generalisatie van de verboden situaties van 2NV en 3NV (en net iets krachtiger: er wordt nog net iets meer verboden). bij: Relationele databases en SQL ©Mattic b.v. 97
bij: Relationele databases en SQL ©Mattic b.v. Voorbeeld Nu extra aanname: elke docent geeft maar één cursus. Dit geeft een nieuw type FA: Ga na: voorbeeldpopulatie is in strijd met nieuwe regel! bij: Relationele databases en SQL ©Mattic b.v. 98
FA impliceert extra uniciteitsregel Ga na dat dit voorbeeld voldoet aan 3NV niet voldoet aan BCNV Dus: kritisch voorbeeld voor BCNV! bij: Relationele databases en SQL ©Mattic b.v. 99
Van 3NV/niet-BCNV naar BCNV Toepassen ‘recept’ afsplitsen ongewenste FA: Merk op: de FA is in de nieuwe structuur triviaal uniciteitsregel 1 is verdwenen! bij: Relationele databases en SQL ©Mattic b.v. 100
Waar is uniciteitsregel 1 gebleven? Weer toevoegen uniciteitsregel 1 als ‘join-uniciteitsregel’: Vraag: hoe (on)bevre- digend is dit? bij: Relationele databases en SQL ©Mattic b.v. 101
De vierde en de vijfde normaalvorm Er zijn nog een vierde (4NV) en een vijfde normaalvorm (5NV) voor de praktijk minder belangrijk zie voor een artikel hierover: de boekwebsite relsql.nl bij: Relationele databases en SQL ©Mattic b.v. 102
Voorbeeld met geneste herhalende groep Gegeven: elke student heeft uniek nummer elke cursus heeft unieke code en naam cijfer inschrijving is (evt. voorlopig) eindcijfer, berekend uit tentamencijfers bij: Relationele databases en SQL ©Mattic b.v. 103
Afsplitsen ‘buitenste’ herhalende groep NB1: sleutels zijn in het boek alleen gedefinieerd voor relationele structuur; géén bezwaar ze ook al toe te passen in een structuur met herhalende groep. NB2: kolom student is verwijssleutel en bevat studentnummers. NB3: (student, cursusnaam) is een alternatieve sleutel. Waarom? bij: Relationele databases en SQL ©Mattic b.v. 104
Afsplitsen ‘binnenste’ herhalende groep 1NV ! bij: Relationele databases en SQL ©Mattic b.v. 105
Test 2NV: zijn er FA’s met determinant die deel is van een sleutel? niet 2NV! afsplitsen FA’s: 2NV NB: aanpassing kolomnamen aan conventies bij: Relationele databases en SQL ©Mattic b.v. 106
Test 3NV: zijn er transitieve FA’s? Nee, die zijn er niet: structuur staat dus ook in 3NV ! bij: Relationele databases en SQL ©Mattic b.v. 107
Standaardisatie docent-acroniemen Examinator-acroniemen zijn in deze structuur niet-gestandaardiseerd Standaardisatie: via aparte tabel met één kolom, die we niet Examinator, maar Docent noemen. NB. ‘examinator’ is een rol die een docent speelt binnen een cursus. Tabel Docent staat los van die context. NB. We zijn nu aan het modelleren, dit is geen normaliseren meer. bij: Relationele databases en SQL ©Mattic b.v. 108
Normalisatie: reikwijdte en beperkingen Normalisatie is een controlemiddel op gegeven structuren Normalisatie leidt doorgaans tot een betere structuur maar: structuur in 3NV / niet-BCNV (kritisch voorbeeld, in de praktijk overigens zeldzaam) kan beter zijn dan doorgenormaliseerd voorbeeld in BCNV Kennis van normalisatie leidt tot goed inzicht in afhankelijkheden tussen gegevens en begrippen als ‘redundantie’ en ‘inconsistentie’ Normalisatie hoeft niet tot standaardisatie te leiden van bepaalde ‘soorten van dingen’, terwijl dat wel gewenst is Normalisatie kijkt alleen naar afzonderlijke tabellen, niet naar de structuur als geheel De beginstructuur is allesbepalend; normalisatie kijkt niet naar alternatieven bij: Relationele databases en SQL ©Mattic b.v. 109
Wat is normalisatie niet? Normalisatie is geen volwaardige databaseontwerp-methode: je kunt pas gaan normaliseren vanuit een gegeven structuur, maar hoe die te vinden is een vak apart normalisatie stopt zodra (bepaalde typen) redundante structuren zijn geëlimineerd normalisatie leidt veelal niet tot standaardisatietabellen voor bepaalde ‘soorten dingen’ Voor databaseontwerp bestaan andere (en betere) methoden bij: Relationele databases en SQL ©Mattic b.v. 110
Informatie uit één tabel Hoofdstuk 6: Informatie uit één tabel 111
bij: Relationele databases en SQL ©Mattic b.v. In dit hoofdstuk … nogmaals: werken met Boekverkenner en IQU projecties datatypen operatoren functies selecties ordening verzamelingsoperatoren bij: Relationele databases en SQL ©Mattic b.v. 112
bij: Relationele databases en SQL ©Mattic b.v. OpenSchool bij: Relationele databases en SQL ©Mattic b.v. 113
Projecties: select … from Bij projectie (‘select’) wordt tabel rij voor rij afgelopen Voorbeeld: = (kolom)alias as mag je weglaten! select naam as cursus, uren, credits * 28 as ECTS_uren from Cursus Resultaat: CURSUS UREN ECTS_UREN ===================== ========= ================= Inleiding informatica 80 84.0 Discrete wiskunde 120 112.0 Databases 120 112.0 Informatiemodelleren 150 140.0 Semantic web 120 112.0 bij: Relationele databases en SQL ©Mattic b.v. 114
bij: Relationele databases en SQL ©Mattic b.v. Projecties: distinct Vergelijk: select uren, credits from Cursus Resultaat: UREN CREDITS ========= ======= 80 3.0 120 4.0 150 5.0 select distinct uren, credits from Cursus Resultaat: UREN CREDITS ========= ======= 80 3.0 120 4.0 150 5.0 Resultaattabel is niet zuiver relationeel! Een tabel in de zin van relatie is immers een verzameling, dus alle rijen verschillend! Distinct maakt er een verzameling van. bij: Relationele databases en SQL ©Mattic b.v. 115
bij: Relationele databases en SQL ©Mattic b.v. Datatypen Gegevens hebben een datatype (vastgelegd in tabeldefinitie) datatype integer gehele getallen numeric(n,m) numeric(n) decimale getallen char(n) tekst vaste lengte varchar(n) tekst variabele lengte date time timestamp datum tijd datum + tijd blob binary large object (bv. plaatje, geluid) bij: Relationele databases en SQL ©Mattic b.v. 116
bij: Relationele databases en SQL ©Mattic b.v. Operatoren operator: ‘token’ voor een bewerking voorbeelden: numerieke operatoren: + - * / alfanumerieke operator: | | datum/tijd-operatoren: - datum/tijd met numeriek: + - stringconcatenatie datums van elkaar aftrekken aantal dagen optellen bij datum/tijd bij: Relationele databases en SQL ©Mattic b.v. 117
bij: Relationele databases en SQL ©Mattic b.v. Functies Functie: voorschrift met een naam om een waarde te berekenen uit andere waarden, de argumenten Format is meestal: f(x, y, …) f is de functienaam x, y, … zijn de argumenten soms wordt de komma vervangen door een ‘betekenisvol’ woord vb. rekenkundige functie: power (x,y) (x tot de macht y) vb. stringfunctie: substring(x from startpos for length) Er kunnen nul argumenten zijn vb.: pi() voor π bij: Relationele databases en SQL ©Mattic b.v. 118
Speciale functies (1): case select student, cursus, case when cijfer >= 6 then ‘voldoende’ when cijfer < 6 then ‘onvoldoende’ else ‘ingeschreven’ end from Tentamen Resultaat: STUDENT CURSUS CASE ======= ====== ============ 1 II voldoende 1 DW onvoldoende 1 DB onvoldoende 1 DB voldoende 2 IM onvoldoende 4 DB ingeschreven bij: Relationele databases en SQL ©Mattic b.v. 119
Speciale functies (2): iff select nr, naam, iif(mentor is null, ‘heeft geen mentor’, ‘heeft mentor’) from Student Resultaat: NR NAAM CASE ========= ====== ================= 1 Berk heeft mentor 2 Tack heeft mentor 3 Bos heeft mentor 4 Eik heeft geen mentor bij: Relationele databases en SQL ©Mattic b.v. 120
bij: Relationele databases en SQL ©Mattic b.v. Selecties: where Let op: kan verwarrend zijn select code, naam, credits -- 3: projectie from Cursus -- 1: brontabel where examinator = ‘DAT’ -- 2: selectie bij: Relationele databases en SQL ©Mattic b.v. 121
bij: Relationele databases en SQL ©Mattic b.v. Ordening: order by Alle inschrijvingen vanaf 15 jan 2012: select * from Inschrijving order by cijfer asc Resultaat: STUDENT CURSUS DATUM CIJFER VRIJSTELLING ========= ====== =========== ====== ============ 4 II 20-jan-2012 <NULL> J 4 DB 29-feb-2012 <NULL> N 1 IM 20-jun-2012 <NULL> N 3 II 16-jan-2012 <NULL> <NULL> 1 DW 19-jan-2012 5 N 2 IM 26-jan-2012 5 N 1 II 12-jan-2012 7 N 1 DB 18-mrt-2012 8 N asc (klimmend ordenen) mag worden weggelaten. nulls voorop! (databasespecifiek) dalend ordenen: desc bij: Relationele databases en SQL ©Mattic b.v. 122
Verzamelingsoperatoren Wiskundige verzamelingsfuncties op twee (rij)verzamelingen A en B: bij: Relationele databases en SQL ©Mattic b.v. 123
Verzamelingsfuncties in SQL: de union select student, cursus, volgnr, cijfer from Tentamen where volgnr >= 2 union where cijfer <= 5 Resultaat: STUDENT CURSUS VOLGNR CIJFER ======= ====== ====== ====== 1 DB 1 5 1 DB 2 8 1 DW 1 5 2 IM 1 4 2 IM 2 5 rijverzameling A A rijverzameling B B A union B (‘vereniging’) Vraag: hoe kan dit veel simpeler? bij: Relationele databases en SQL ©Mattic b.v. 124
Zinvol voorbeeld union Tentamens met voldoende en tekst ‘eerste poging’ of ‘herkansing’: -- eerste pogingen select student, cursus, datum, ‘eerste poging’ poging from Tentamen where volgnr = 1 union -- herkansingen select student, cursus, datum, ‘herkansing’ where volgnr >= 2 Resultaat: STUDENT CURSUS DATUM POGING ======= ====== =========== ============= 1 DB 19-apr-2012 eerste poging 1 DB 26-jun-2012 herkansing 1 DW 17-apr-2012 eerste poging 1 II 17-apr-2012 eerste poging 2 IM 06-apr-2012 eerste poging 2 IM 11-jun-2012 herkansing 4 DB 26-jun-2012 eerste poging bij: Relationele databases en SQL ©Mattic b.v. 125
Nogmaals: demonstratie Boekverkenner / IQU Voorbeelddatabase: OpenSchool databasediagrammen scripts Installatie van voorbeelddatabase / in- en uitloggen Uitvoeren van query’s vanuit de tekst Werken met de Interactive Query Utility bij: Relationele databases en SQL ©Mattic b.v. 126
Informatie uit meerdere tabellen: joins Hoofdstuk 7: Informatie uit meerdere tabellen: joins 127
bij: Relationele databases en SQL ©Mattic b.v. In dit hoofdstuk … Inner joins Outer joins Joinoperatoren Joins over een brede sleutel Samengestelde joins Joins van tabel met zichzelf (autojoins) Joins over niet-sleutelverwijzing Navigatiepaden bij: Relationele databases en SQL ©Mattic b.v. 128
bij: Relationele databases en SQL ©Mattic b.v. OpenSchool bij: Relationele databases en SQL ©Mattic b.v. 129
Inner join van Student en Docent join = verbrede tabel (via verwijzing) bij: Relationele databases en SQL ©Mattic b.v. 130
Joinen als denormaliseren Jointabel bevat functionele afhankelijkheden met niet-unieke determinant: voldoet dus niet aan 3NV. (In database zou dat redundantie geven.) bij: Relationele databases en SQL ©Mattic b.v. 131
bij: Relationele databases en SQL ©Mattic b.v. Join-navigatiepad Navigatiepad loopt (in dit geval!) vanaf Student (startpunt) via de verwijzende sleutel naar Docent. bij: Relationele databases en SQL ©Mattic b.v. 132
bij: Relationele databases en SQL ©Mattic b.v. De inner join in SQL Stap 1 : producttabel incl. zinloze combinaties! Resultaat: NR NAAM MENTOR ACR NAAM VERVANGER VAKGROEP ========= ====== ====== ====== ========= ========= ======== 1 Berk DAT DAT C.Date COD IS 2 Tack DAT DAT C.Date COD IS 3 Bos COD DAT C.Date COD IS 4 Eik <NULL> DAT C.Date COD IS 1 Berk DAT COD E.Codd <NULL> IS 2 Tack DAT COD E.Codd <NULL> IS 3 Bos COD COD E.Codd <NULL> IS 4 Eik <NULL> COD E.Codd <NULL> IS 1 Berk DAT BAC C.Bachman DAT ST 2 Tack DAT BAC C.Bachman DAT ST 3 Bos COD BAC C.Bachman DAT ST 4 Eik <NULL> BAC C.Bachman DAT ST select * from Student, Docent producttabel: alle rijen van Student gecombineerd met alle rijen van Docent bij: Relationele databases en SQL ©Mattic b.v. 133
bij: Relationele databases en SQL ©Mattic b.v. Stap 2 : selectie van producttabel select * from Student S, Docent D producttabel where S.mentor = D.acr selectie: alleen de zinvolle rijen uit Student uit Docent NR NAAM MENTOR ACR NAAM VERVANGER VAKGROEP ========= ====== ====== ====== ========= ========= ======== 1 Berk DAT DAT C.Date COD IS 2 Tack DAT DAT C.Date COD IS 3 Bos COD DAT C.Date COD IS 4 Eik <NULL> DAT C.Date COD IS 1 Berk DAT COD E.Codd <NULL> IS 2 Tack DAT COD E.Codd <NULL> IS 3 Bos COD COD E.Codd <NULL> IS 4 Eik <NULL> COD E.Codd <NULL> IS 1 Berk DAT BAC C.Bachman DAT ST 2 Tack DAT BAC C.Bachman DAT ST 3 Bos COD BAC C.Bachman DAT ST 4 Eik <NULL> BAC C.Bachman DAT ST Resultaattabel bij: Relationele databases en SQL ©Mattic b.v. 134
bij: Relationele databases en SQL ©Mattic b.v. Stap 3 : projectie (schrap primaire sleutel van oudertabel select S.nr, S.naam, S.mentor, D.naam, D.vervanger, D.vakgroep from Student S, Docent D where S.mentor = D.acr inner join! Resultaat: NR NAAM MENTOR NAAM VERVANGER VAKGROEP ========= ====== ====== ====== ========= ======== 1 Berk DAT C.Date COD IS 2 Tack DAT C.Date COD IS 3 Bos COD E.Codd <NULL> IS bij: Relationele databases en SQL ©Mattic b.v. 135
Inner join met extra conditie Geef van elke cursus die een examinator heeft en die 4 of minder credits hebben, de cursusnaam en het acroniem en de naam van de examinator. select C.naam, C.examinator, D.naam from Cursus C, Docent D where C.examinator = D.acr and C.credits <= 4 joinconditie aanvullende conditie Zet de joinconditie voorop: kwestie van goede programmeerstijl bij: Relationele databases en SQL ©Mattic b.v. 136
bij: Relationele databases en SQL ©Mattic b.v. Inner join-operator select C.naam, C.examinator, D.naam from Cursus C, Docent D where C.examinator = D.acr and C.credits <= 4 Equivalent, met inner join-operator: select C.naam, C.examinator, D.naam from Cursus C inner join Docent D on C.examinator = D.acr where C.credits <= 4 kortweg: join bij: Relationele databases en SQL ©Mattic b.v. 137
Left outer join van Student en Docent tabelverbreding op de outer join-manier: elke rij wordt verbreed bij: Relationele databases en SQL ©Mattic b.v. 138 138
De left outer join in SQL Gewenst resultaat: NR NAAM MENTOR NAAM VERVANGER VAKGROEP ========= ====== ====== ====== ========= ======== 1 Berk DAT C.Date COD IS 2 Tack DAT C.Date COD IS 3 Bos COD E.Codd <NULL> IS 4 Eik <NULL> <NULL> <NULL> <NULL> de extra rij (student zonder mentor) We maken deze ‘left outer join’ als een inner join met een union: select S.nr, S.naam, S.mentor, D.naam, D.vervanger, D.vakgroep from Student S, Docent D where S.mentor = D.acr union select nr, naam, mentor, null, null, null from Student where mentor is null ‘left’: van linker tabel komen alle rijen in het resultaat bij: Relationele databases en SQL ©Mattic b.v. 139
De left outer join-operator Left outer join, via union: select S.nr, S.naam, S.mentor, D.naam, D.vervanger, D.vakgroep from Student S, Docent D where S.mentor = D.acr union select nr, naam, mentor, null, null, null from Student where mentor is null Equivalent en simpeler, met de left outer join-operator: select S.nr, S.naam, S.mentor, D.naam, D.vervanger, D.vakgroep from Student S left outer join Docent D on S.mentor = D.acr left: linker tabeloperand wordt verbreed bij: Relationele databases en SQL ©Mattic b.v. 140
Left outer join met oudertabel voorop (1) Geef alle docenten, met hun acroniem en naam en, voor zover ze er zijn, het nummer en de naam van de studenten waarvan zij mentor zijn. Merk op: overzicht met herhalende groep gevraagd! Namelijk: ACR NAAM ---STUDENTEN--- (NR NAAM ) ------ --------- -------- ------ DAT C.Date 1 Berk 2 Tack COD E.Codd 3 Bos BAC C.Bachman <NULL> <NULL> Kan niet in SQL! bij: Relationele databases en SQL ©Mattic b.v. 141
Left outer join met oudertabel voorop (2) Meest in de buurt komt de volgende oplossing: select D.acr, D.naam, S.nr, S.naam from Docent D left outer join Student S on D.acr = S.mentor Resultaattabel: ACR NAAM NR NAAM ====== ========= ========= ====== DAT C.Date 1 Berk DAT C.Date 2 Tack COD E.Codd 3 Bos BAC C.Bachman <NULL> <NULL> ACR NAAM ---STUDENTEN--- (NR NAAM ) ------ --------- -------- ------ DAT C.Date 1 Berk 2 Tack COD E.Codd 3 Bos BAC C.Bachman <NULL> <NULL> genormaliseerde versie van gevraagd overzicht bij: Relationele databases en SQL ©Mattic b.v. 142
De right en full outer join De left outer join volstaat! Aanname daarbij: alleen ‘homogene’ overzichten, d.w.z. van één soort van ding, bepaald door één starttabel navigatie starten in de juiste (start)tabel volgorden in SQL-statement aanpassen aan het navigatiepad (zie voorbeelden in cursusboek) bij: Relationele databases en SQL ©Mattic b.v. 143
Joins over een brede sleutel Gevraagd: voor elk tentamen het aantal dagen dat is verstreken sinds de cursusinschrijving. De benodigde tabellen zijn weergegeven in figuur 7.7 SQL: stap voor stap (zie Boek / Boekverkenner). Uiteindelijk: select T.student, T.cursus, T.volgnr, T.datum - I.datum aantal_dagen_na_inschrijving from Tentamen T join Inschrijving I on T.student = I.student and T.cursus = I.cursus bij: Relationele databases en SQL ©Mattic b.v. 144
Samengestelde joins (1) Geef een overzicht van alle herkansingstentamens, waarbij naast het studentnummer de naam van de student wordt vermeld. Verder moet in plaats van de cursuscode de naam van de cursus worden vermeld. De starttabel en het navigatiepad volgen uit de vraagstelling: Deze vinden we terug in de SQL-oplossing! bij: Relationele databases en SQL ©Mattic b.v. 145
Samengestelde joins (2) SQL: select T.student, C.naam, T.volgnr, T.datum, T.cijfer from Tentamen T join Inschrijving I on T.student = I.student and T.cursus = I.cursus join Student S on I.student = S.nr join Cursus C on I.cursus = C.code where T.volgnr >= 2 bij: Relationele databases en SQL ©Mattic b.v. 146
Gemengd gebruik van inner en outer joins Geef van elke inschrijving waarvoor een vrijstelling is verleend het studentnummer, de cursuscode, de datum en – voor zover van toepassing – de naam van de examinator. Starttabel en navigatiepad: SQL: select I.student, I.cursus, I.datum, D.naam examinator from Inschrijving I join Cursus C on I.cursus = C.code left outer join Docent D on C.examinator = D.acr where I.vrijstelling = 'J' NB. Verwijzing van Inschrijving naar Cursus is verplicht, dus geen verschil inner en outer join. bij: Relationele databases en SQL ©Mattic b.v. 147
bij: Relationele databases en SQL ©Mattic b.v. Autojoins Vraagstelling: Geef van alle docenten die een vervanger hebben, het acroniem en de naam en ook het acroniem en de naam van de vervanger. Aanpak: Tabel Docent (starttabel) doorlopen en via de verwijzing in dezelfde tabel de vervanger opzoeken. Truc: ga - conceptueel - uit van twee exemplaren van Docent, één in de rol van docenten waarvoor het overzicht gemaakt wordt, en één in de rol van mogelijke vervangers. bij: Relationele databases en SQL ©Mattic b.v. 148
Autojoin: joinen met ander exemplaar van dezelfde tabel Vat een recursieve verwijzing op als een virtuele exemplaren van de ene tabel Docent, met elk een eigen naam (alias), waarvan de één naar de ander verwijst: Recursieve verwijzing: opvatten als gewone verwijzing! Welge- kozen aliassen geven de rollen weer van de tabelexemplaren in het probleem. Navigatiepad: SQL: select D.acr, D.naam, V.acr, V.naam from Docent D join Docent V on D.vervanger = V.acr bij: Relationele databases en SQL ©Mattic b.v. 149
Virtueel tabelexemplaar is volledige tabel! Met populatie: Elk virtueel tabelexemplaar is de volledige tabel (gebruikt in een zekere rol) bij: Relationele databases en SQL ©Mattic b.v. 150
Een left outer autojoin in SQL Geef van alle docenten het acroniem en de naam en als ze een vervanger hebben ook het acroniem en de naam van de vervanger. select D.acr, D.naam, V.acr, V.naam from Docent D left outer join Docent V on D.vervanger = V.acr ACR NAAM ACR NAAM ====== ========= ====== ====== DAT C.Date COD E.Codd COD E.Codd <NULL> <NULL> BAC C.Bachman DAT C.Date Resultaat: bij: Relationele databases en SQL ©Mattic b.v. 151
Ouders zonder kind (1) Probleem: geef alle cursussen (code en naam) waarvoor geen enkele inschrijving bestaat. Algemeen: geef alle ouderrijen waar geen kindrij bij hoort. We lossen dit probleem op met een outer join. Later doen we het eenvoudiger, met een subselect. Maar deze manier is leerzaam en kan ook erg snel zijn (bij grote databases)! Merk op: er wordt precies gevraagd naar de ouderrijen die verdwijnen bij de inner join (en behouden blijven bij de left outer join) van Cursus en Inschrijving. Hoe herkennen we die rijen in de left outer join? bij: Relationele databases en SQL ©Mattic b.v. 152
bij: Relationele databases en SQL ©Mattic b.v. Ouders zonder kind (2) Eerst volledige left outer join: select * from Cursus C left outer join Inschrijving I on C.code = I.cursus CODE NAAM UREN CREDITS EXAMINATOR STUDENT CURSUS DATUM CIJFER VRIJSTELLING ====== ===================== ========= ======= ========== ========= ====== =========== ====== ============ II Inleiding informatica 80 3.0 BAC 1 II 12-jan-2012 7 N II Inleiding informatica 80 3.0 BAC 2 II 12-jan-2012 <NULL> J II Inleiding informatica 80 3.0 BAC 3 II 16-jan-2012 <NULL> <NULL> II Inleiding informatica 80 3.0 BAC 4 II 20-jan-2012 <NULL> J DW Discrete wiskunde 120 4.0 DAT 1 DW 19-jan-2012 5 N DW Discrete wiskunde 120 4.0 DAT 2 DW 12-jan-2012 <NULL> J DB Databases 120 4.0 COD 1 DB 18-mrt-2012 8 N DB Databases 120 4.0 COD 4 DB 29-feb-2012 <NULL> N IM Informatiemodelleren 150 5.0 DAT 1 IM 20-jun-2012 <NULL> N IM Informatiemodelleren 150 5.0 DAT 2 IM 26-jan-2012 5 N SW Semantic web 120 4.0 <NULL> <NULL> <NULL> <NULL> <NULL> <NULL> (of andere verplichte kolom van kindtabel) select C.code, C.naam from Cursus C left outer join Inschrijving I on C.code = I.cursus where I.student is null Dan conditie toevoegen: zit niet in inner join: ouder zonder kind! bij: Relationele databases en SQL ©Mattic b.v. 153
Statistische informatie Hoofdstuk 8: Statistische informatie 154
bij: Relationele databases en SQL ©Mattic b.v. In dit hoofdstuk … Statistische functies Scheve query’s Groeperen Voorwaarden aan groepen: having Groeperen is denormaliseren Statistische joinquery’s Het conceptuele algoritme bij: Relationele databases en SQL ©Mattic b.v. 155
bij: Relationele databases en SQL ©Mattic b.v. OpenSchool bij: Relationele databases en SQL ©Mattic b.v. 156
Statistische functies Hoeveel inschrijvingen zijn er voor de cursus met code II? select count(*) aantal -- 3 from Inschrijving -- 1 where cursus = 'II' -- 2 één statistische waarde over hele tabel (één groep) Resultaat: AANTAL ========= 4 bij: Relationele databases en SQL ©Mattic b.v. 157
bij: Relationele databases en SQL ©Mattic b.v. ‘Scheve’ query’s één waarde per rij één waarde voor hele tabel Wat deugt hier niet aan? select code, count(*) from Cursus foutieve ´scheve´ query! bij: Relationele databases en SQL ©Mattic b.v. 158
bij: Relationele databases en SQL ©Mattic b.v. Groeperen Aantal inschrijvingen per cursus: select cursus, count(*) aantal -- 3 from Inschrijving -- 1 group by cursus -- 2 tabel Inschrijving wordt opgedeeld in groepen van rijen: - per cursus één groep; - één statistische waarde per groep (= per cursus) Resultaat: CURSUS AANTAL ====== ========= DB 2 DW 2 II 4 IM 2 bij: Relationele databases en SQL ©Mattic b.v. 159
bij: Relationele databases en SQL ©Mattic b.v. Verfijnd groeperen Groeperen over twee of meer kolommen geeft een verfijndere groepenindeling. Voorbeeld: Aantallen tentamens per inschrijving (= per combinatie student/cursus): select student, cursus, count(*) from Tentamen group by student, cursus Resultaat: STUDENT CURSUS COUNT ======= ====== ========= 1 DB 2 1 DW 1 1 II 1 2 IM 2 4 DB 1 bij: Relationele databases en SQL ©Mattic b.v. 160
Voorwaarden aan groepen: having Per cursus aantal inschrijvingen zonder vrijstelling. Beperken tot cursussen waar- voor dat aantal tenminste 2 is: Resultaat: CURSUS AANTAL ====== ========= DB 2 IM 2 select cursus, count(*) aantal -- 5 from Inschrijving -- 1 where vrijstelling = 'N' -- 2 group by cursus -- 3 having count(*) >= 2 -- 4 bij: Relationele databases en SQL ©Mattic b.v. 161
Groeperen als denormaliseren (1) Geef voor elke cursus met vrijstelling = ‘ N’: cursuscode, aantal inschrijvingen en gemiddelde cijfer. Oplossing: select cursus, -- 4 count(*) aantal, -- avg(cijfer) gemiddelde_cijfer -- from Inschrijving -- 1 where vrijstelling = ‘N’ -- 2 group by cursus -- 3 Eindresultaat (na stap 4): CURSUS AANTAL GEMIDDELDE_CIJFER ====== ========= ================= DB 2 8 DW 1 5 II 1 7 IM 2 5 bij: Relationele databases en SQL ©Mattic b.v. 162
Groeperen als denormaliseren (2) Na stap 2: select … from Inschrijving -- 1 where vrijstelling = ‘N’ -- 2 is het tussenresultaat: STUDENT CURSUS DATUM CIJFER VRIJSTELLING ========= ====== =========== ====== ============ 1 II 12-jan-2012 7 N 1 DW 19-jan-2012 5 N 1 DB 18-mrt-2012 8 N 1 IM 20-jun-2012 <NULL> N 2 IM 26-jan-2012 5 N 4 DB 29-feb-2012 <NULL> N In stap 3 gaan we dit groeperen op kolom cursus bij: Relationele databases en SQL ©Mattic b.v. 163
Groeperen als denormaliseren (3) Bij stap 3 – het groeperen op cursus – wordt een herhalende groep gemaakt: select … from Inschrijving -- 1 where vrijstelling = ‘N’ -- 2 group by cursus -- 3 STUDENT CURSUS DATUM CIJFER VRIJSTELLING ========= ====== =========== ====== ============ 1 DB 18-mrt-2012 8 N 4 29-feb-2012 <NULL> N ------------------------------------------------ 1 DW 19-jan-2012 5 N 1 II 12-jan-2012 7 N 1 IM 20-jun-2012 <NULL> N 2 26-jan-2012 5 N Dit is tabel met vier rijen en twee kolommen, waarvan één een herhalende groep! bij: Relationele databases en SQL ©Mattic b.v. 164
Groeperen als denormaliseren (4) Nog duidelijker wanneer we kolom cursus voorop zetten: CURSUS STUDENT DATUM CIJFER VRIJSTELLING ====== ========= =========== ====== ============ DB 1 18-mrt-2012 8 N 4 29-feb-2012 <NULL> N ------------------------------------------------ DW 1 19-jan-2012 5 N II 1 12-jan-2012 7 N IM 1 20-jun-2012 <NULL> N 2 26-jan-2012 5 N voor elke groep: count(*), avg(cijfer), … Zo ontstaat het eindresultaat: CURSUS AANTAL GEMIDDELDE_CIJFER ====== ========= ================= DB 2 8 DW 1 5 II 1 7 IM 2 5 bij: Relationele databases en SQL ©Mattic b.v. 165
Statistische joinquery’s Gevraagd: cursussen met hun hun aantallen inschrijvingen Merk op: tabelverbreding op de inner join manier: we missen cursus SW starttabel is Cursus: navigatie is ouder richting kind, tegen de richting van de verwijzing in bij: Relationele databases en SQL ©Mattic b.v. 166
Starttabel en navigatierichting bij statistische query bij: Relationele databases en SQL ©Mattic b.v. 167
Statistische joinquery in SQL (Gevraagd: cursussen met hun aantallen inschrijvingen) Poging: select C.code, C.naam, count(*) aantal_inschrijvingen from Cursus C join Inschrijving I on C.code = I.cursus group by C.code Conceptueel is dit goed: we moeten immers groepen hebben met gelijke cursuscode. Die hebben dan vanzelf ook dezelfde cursusnaam (waarom?) bij: Relationele databases en SQL ©Mattic b.v. 168
Onverwacht verfijnd groeperen De juiste oplossing: FA select C.code, C.naam, count(*) aantal_inschrijvingen from Cursus C join Inschrijving I on C.code = I.cursus group by C.code, C.naam verplicht verfijnd groeperen, ondanks de functionele afhankelijkheid bij: Relationele databases en SQL ©Mattic b.v. 169
Statistische outer joinquery’s Gevraagd: alle cursussen met hun aantallen inschrijvingen Merk op: nu ook cursus SW (aangevuld met null) bij: Relationele databases en SQL ©Mattic b.v. 170
Statistische outer joinquery in SQL (alle cursussen met hun aantallen inschrijvingen) Juiste oplossing: count(I.cursus) Poging: select C.code, C.naam, count(*) aantal_inschrijvingen from Cursus C left outer join Inschrijving I on C.code = I.cursus group by C.code, C.naam Resultaat van poging: CODE NAAM AANTAL_INSCHRIJVINGEN ====== ===================== ===================== DB Databases 2 DW Discrete wiskunde 2 II Inleiding informatica 4 IM Informatiemodelleren 2 SW Semantic web 1 Waarom een 1? Hoe op te lossen? bij: Relationele databases en SQL ©Mattic b.v. 171
Genest groeperen (vb: ‘minimax’-probleem) genest groeperen = groeperen van groeperingsresultaat statistische waarde van statistische waarden select count(*) from Inschrijving group by cursus Aantallen inschrijvingen per cursus: select avg(count(*)) from Inschrijving group by cursus Gemiddeld aantal inschrijvingen per cursus : (in Firebird moet dit anders) Resultaat: COUNT ========= 2 4 Resultaat: AVG(COUNT(*)) ------------- 3.6666667 bij: Relationele databases en SQL ©Mattic b.v. 172
Nogmaals een ‘scheve’ query Gevraagd: de cursus (of cursussen) met het grootste aantal inschrijvingen Poging: select cursus, max(count(*)) from Inschrijving group by cursus Waarom is dit een ‘scheve’ query en dus fout? bij: Relationele databases en SQL ©Mattic b.v. 173
De conceptuele verwerkingsvolgorde (1) Gevraagd: overzicht van inschrijvingen die met een voldoende zijn afgesloten en waarvan aantal tentamens 2 is of hoger. Orden op dat aantal, van hoog naar laag. Oplossen: vanuit ‘bekende’ conceptuele verwerkingsvolgorde’: select I.student, I.cursus, count(*) from 5. projectie op I.student, I.cursus, met extra statistische kolom Inschrijving I, Tentamen T 1. brontabel (cartesisch product) where I.student = T.student and I.cursus = T.cursus and I.cijfer >= 6 2. rijselectie van brontabel group by I.student, I.cursus 3. groeperen (geeft één rij per inschrijving, met herhalende groep) having count(*) >= 2 4. rijselectie van gegroepeerde tabel order by count(*) 6. ordening op aantal (count(*)) met opzet hier zonder joinoperator! bij: Relationele databases en SQL ©Mattic b.v. 174
De conceptuele verwerkingsvolgorde (2) brontabel where group by having select … from order by De werkelijke volgorde kan anders zijn! bij: Relationele databases en SQL ©Mattic b.v. 175
Hoofdstuk 9: Subselects en views 176
bij: Relationele databases en SQL ©Mattic b.v. In dit hoofdstuk … subselects als oplossing van deelproblemen subselect in: … where-clausule … select-clausule … from-clausule … having-clausule (zie boek) gecorreleerde en niet-gecorreleerde subselects subselects en joins: navigatie via subselect(s) gecorreleerde subselects … met (not) exists geneste subselects views als oplossing van deelproblemen bij: Relationele databases en SQL ©Mattic b.v. 177
bij: Relationele databases en SQL ©Mattic b.v. OpenSchool bij: Relationele databases en SQL ©Mattic b.v. 178
bij: Relationele databases en SQL ©Mattic b.v. Waar een subselect? (select ... ...) select ... from ... where ... group by ... having ... In principe (conceptueel): overal waar een relationele expressie (tabel) of atomaire waarde betekenisvol is. bij: Relationele databases en SQL ©Mattic b.v. 179
Subselect in where-clausule Gevraagd: geef de oudste inschrijving (of inschrijvingen). Vermeld studentnummer, cursuscode en datum. Stapsgewijs oplossen: select student, cursus, datum from Inschrijving where datum = -- de vroegste inschrijvingsdatum stap 1 ( select min(datum) from Inschrijving) stap 2 Deze subselect is niet-gecorreleerd: kan a.h.w. worden uitgeknipt en zelfstandig worden uitgevoerd. bij: Relationele databases en SQL ©Mattic b.v. 180
Subselect in select-clausule (1) Gevraagd: van elke cursus de cursuscode, de cursusnaam en het aantal inschrijvingen. Stapsgewijs oplossen: select code, naam, -- aantal inschrijvingen from Cursus deelprobleem ( select count(*) from Inschrijving where cursus = C.code) C met oplossing subselect is gecorreleerd: voor elke cursus van de hoofdselect andere subselect bij: Relationele databases en SQL ©Mattic b.v. 181
Subselect in select-clausule (2) De oplossing: select code, naam, (-- aantal inschrijvingen select count(*) from Inschrijving where cursus = C.code) from Cursus C kunnen we nog als volgt herschrijven met een kolomalias: select code, naam, (select count(*) from Inschrijving where cursus = C.code) aantal_inschrijvingen from Cursus C De kolomnaam (alias) vervangt nu het commentaar. bij: Relationele databases en SQL ©Mattic b.v. 182
Subselect in from-clausule Gevraagd: maximum van de aantallen inschrijvingen per cursus. (minimax-probleem!) Stapsgewijs oplossen: select max(aantal_inschrijvingen) from deelprobleem gevraagd: tabel met een kolom aantal_inschrijvingen (per cursus) (select count(*) aantal_inschrijvingen from Cursus C join Inschrijving I on C.code = I.cursus group by C.code) bij: Relationele databases en SQL ©Mattic b.v. 183
Subselectnavigatie en joinnavigatie (gevraagd: van elke cursus: code, naam en aantal inschrijvingen) met subselectnavigatie: select code, naam, (select count(*) from Inschrijving where cursus = C.code) aantal_inschrijvingen from Cursus C met joinnavigatie: select C.code, C.naam, count(I.cursus) from Cursus C left outer join Inschrijving I on C.code = I.cursus group by C.code, C.naam Bij beide stap je over van Cursus naar Inschrijving: navigatie tegen richting verwijzende sleutel in (‘van één naar veel’). bij: Relationele databases en SQL ©Mattic b.v. 184
Subselect met verzamelingenoperator ‘in’ Gevraagd: alle cursussen (code en naam) die cursus DW als voorkennis eisen stap 1 select code, naam from Cursus where code in -- verzameling codes van cursussen met voorkennis DW stap 2 ( select cursus from Voorkenniseis where voorkennis = 'DW') bij: Relationele databases en SQL ©Mattic b.v. 185
Navigatie over brede sleutel Gevraagd: inschrijvingen (studentnummer, cursuscode en datum) waarvoor twee maal of vaker tentamen is gedaan. select student, cursus, datum from Inschrijving where (student, cursus) in -- verzameling combinaties (student, cursus) uit Tentamen die daarin minstens twee keer voorkomen stap 1 ( select student, cursus from Tentamen group by student, cursus having count(*) >= 2) stap 2 (kan niet in Firebird: zie boek voor trucje) bij: Relationele databases en SQL ©Mattic b.v. 186
Ongecorreleerde en gecorreleerde subselects 1. Gevraagd: de vroegste inschrijvingen: twee exemplaren van Inschrijving! select student, cursus, datum from Inschrijving where datum = (-- de vroegste inschrijvingsdatum select min(datum) from Inschrijving) zelfstandig uit te voeren (ongecorreleerd) 2. Gevraagd: de vroegste inschrijvingen per cursus: select student, cursus, datum from Inschrijving I where datum = (-- de vroegste inschrijvingsdatum bij -- de cursus van ‘deze’ inschrijving select min(datum) from Inschrijving where cursus = I.cursus) niet zelfstandig uit te voeren (gecorreleerd) bij: Relationele databases en SQL ©Mattic b.v. 187
Gecorreleerde subselect met exists Gevraagd: cursussen waarvoor één of meer vrijstellingen zijn verleend. Oplossing 1: ongecorreleerde subselect met in select code, naam from Cursus where code in (select cursus from Inschrijving where vrijstelling = 'J') Oplossing 2: gecorreleerde subselect met exists select code, naam from Cursus C where exists (select * from Inschrijving where cursus = C.code and vrijstelling = 'J') geeft true als verzameling niet leeg bij: Relationele databases en SQL ©Mattic b.v. 188
Nogmaals: ouders zonder kind Probleem: geef alle cursussen (code en naam) waarvoor geen enkele inschrijving bestaat. Subselect met ‘not in’: select code, naam from Cursus where code not in (select cursus from Inschrijving) Subselect met ‘not exists’: select code, naam from Cursus C where not exists (select * from Inschrijving where cursus = C.code) bij: Relationele databases en SQL ©Mattic b.v. 189
bij: Relationele databases en SQL ©Mattic b.v. Geneste subselects Probleem: welke docenten (acroniem) zijn begeleider van de cursus met de meeste inschrijvingen? Navigatiepad volgt al uit de vraagstelling: 1 2 3 bij: Relationele databases en SQL ©Mattic b.v. 190
Oplossing in stappen volgt navigatiepad select acr, naam from Docent where acr in (-- de verzameling acroniemen van docenten die begeleider zijn -- zijn van de cursus(sen) met de meeste inschrijvingen stap 1 select docent from Begeleider where cursus in (-- verzameling codes van cursussen met de meeste inschrijvingen stap 2 select cursus from Inschrijving group by cursus having count (*) = (-- maximum aantal inschrijvingen per cursus stap 3 select max(aantal_inschrijvingen) from (select count(*) aantal_inschrijvingen from Inschrijving group by cursus)))) stap 4 Navigatiepad omvat zelfs twee exemplaren van Inschrijving! bij: Relationele databases en SQL ©Mattic b.v. 191
bij: Relationele databases en SQL ©Mattic b.v. Views Een view is een ‘ named query’: een select-query die we kunnen bewaren en gebruiken als een databasetabel Een view kan als alternatief dienen voor een subselect Views kunnen we (dus) net als subselects gebruiken om een probleem op te delen in deelproblemen bij: Relationele databases en SQL ©Mattic b.v. 192
Voorbeeld van een view (1) Gevraagd: code, naam en aantal inschrijvingen van de cursus(sen) met de meeste inschrijvingen. Oplossing 1: met subselect select C.code, C.naam, count(*) from Cursus C join Inschrijving I on C.code = I.cursus group by C.code, C.naam having count(*) = (--maximum aantal inschrijvingen per cursus select max(aantal_inschrijvingen) from (select count(*) aantal_inschrijvingen from Inschrijving group by cursus)) - complexe hoofdquery met complexe (geneste) subselect ter vereenvoudiging maken we een view voor het volgende deelprobleem: het aantal inschrijvingen per cursus bij: Relationele databases en SQL ©Mattic b.v. 193
Voorbeeld van een view (2) Oplossing 2: met een view en een (simpeler) subselect: - Definitie van de view (genaamd vCursus) create view vCursus (code, naam, aantal_inschrijvingen) as select C.code, C.naam, count(*) from Cursus C join Inschrijving I on C.code = I.cursus group by C.code, C.naam Hiermee is een deelprobleem opgelost. - Oplossing van het volledige probleem is nu eenvoudig: select code, naam, aantal_inschrijvingen from vCursus where aantal_inschrijvingen = (select max(aantal_inschrijvingen) from vCursus) bij: Relationele databases en SQL ©Mattic b.v. 194
Wijzigen van een database-inhoud Hoofdstuk 10: Wijzigen van een database-inhoud 195
bij: Relationele databases en SQL ©Mattic b.v. In dit hoofdstuk … Transacties Het insert-statement Het delete-statement Het update-statement Integriteitsregels bij: Relationele databases en SQL ©Mattic b.v. 196
OpenSchool
bij: Relationele databases en SQL ©Mattic b.v. Transacties transactie = reeks SQL-statements die ofwel in hun geheel, ofwel in het geheel niet worden uitgevoerd. commitmoment = moment waarop de transactie definitief wordt tevens einde van de transactie expliciet via commit-statement impliciet via DDL-statement DDL = subtaal voor structuurverandering, bv. create table rollback: terugdraaien van transactie statement: rollback bij: Relationele databases en SQL ©Mattic b.v. 198
Soorten databases m.b.t. transacties Aard en frequentie van transacties bepalen hoe een database ‘leeft’. Verschillende ‘levenswijzen’: OnLine Transational Processing (OLTP) database online gestuurd via programmatuur en (frequent) gevuld vanuit automaten of bv. internet Transactionele bedrijfssystemen bijhouden van dagelijkse veranderingen van de bedrijfswerkelijkheid (klanten, bestellingen, …) Datawarehouses verzamelen historiegegevens en transformeren tot waardevolle informatie
Transactie afsluiten met commit(moment) of rollback transactie afgesloten met commitmoment: transactie afgesloten met rollback: bij: Relationele databases en SQL ©Mattic b.v. 200
bij: Relationele databases en SQL ©Mattic b.v. Transactiemodellen Impliciete transactiemodel: na elk commitmoment of rollback start nieuwe transactie Expliciete transactiemodel: start transactie pas na start transaction-statement; tot die tijd is elk statement een transactie op zichzelf Meer hierover in hoofdstuk 15 ‘Transacties en concurrency’ … met name over hoe transacties van verschillende gebruikers elkaar in de weg kunnen zitten en oplossingen daarvoor bij: Relationele databases en SQL ©Mattic b.v. 201
Het insert-statement: poging tot invoegen Voorbeeld enkelvoudige insert: insert into Student values (5, 'Stam', null) Alternatief met kolommenlijst (en weglating null-waarde): insert into Student (nr, naam) bij: Relationele databases en SQL ©Mattic b.v. 202
bij: Relationele databases en SQL ©Mattic b.v. Meervoudige insert Voorbeeld: nieuwe tabel DWCursus maakt deel uit van datawarehouse met statistische informatie. Kolom begeleidJN moet waarde ‘J’ of ‘N’ krijgen al naar gelang een cursus één of meer begeleiders heeft. insert into DWCursus select code, naam, iif(exists (select * from Begeleider where cursus = C.code), 'J', 'N') from Cursus C bij: Relationele databases en SQL ©Mattic b.v. 203
Het delete-statement: poging tot verwijderen denk aan: referentiële integriteitsregel - cascading deletes Verschil tussen: delete from Cursus where code = ‘II‘ en delete from Cursus where code = ‘SW‘ bij: Relationele databases en SQL ©Mattic b.v. 204
Het update-statement: poging tot wijzigen Voorbeeld eenvoudige update: update Cursus -- 1 set uren = 140, credits = 5 -- 3 where code = 'DW' -- 2 Let op de (conceptuele) volgorde! update Cursus set uren = 140, credits = 5 where code = 'DW' toekenning (‘maak gelijk aan’) gelijkheid (‘is gelijk aan’) bij: Relationele databases en SQL ©Mattic b.v. 205
bij: Relationele databases en SQL ©Mattic b.v. Update van elke rij Update van elke rij: update Cursus set uren = uren * 1.1 nieuwe waarde van uren oude waarde van uren bij: Relationele databases en SQL ©Mattic b.v. 206
bij: Relationele databases en SQL ©Mattic b.v. Update met subselect Maak elk urenaantal gelijk aan het gemiddelde aantal uren. Poging: update Cursus set uren = (select avg(uren) from Cursus) Inspectie van tabel Cursus geeft: CODE NAAM UREN ====== ===================== ========= II Inleiding informatica 118 DW Discrete wiskunde 125 DB Databases 126 IM Informatiemodelleren 127 SW Semantic web 123 (ongecorreleerde update) verklaring? bij: Relationele databases en SQL ©Mattic b.v. 207
Update met gecorreleerde subselect Extra kolom tabel Cursus: alter table Cursus add aantal_inschrijvingen integer Vullen: update Cursus C set aantal_inschrijvingen = (-- aantal inschrijvingen voor ‘deze’ cursus select count(*) from Inschrijving where cursus = C.code) bij: Relationele databases en SQL ©Mattic b.v. 208