De presentatie wordt gedownload. Even geduld aub

De presentatie wordt gedownload. Even geduld aub

Relationele databases en SQL

Verwante presentaties


Presentatie over: "Relationele databases en SQL"— Transcript van de presentatie:

1 Relationele databases en SQL
hoofdstuk 1 t/m 10 1

2 © 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.

3 bij: Relationele databases en SQL ©Mattic b.v.
Cursusmateriaal cursusboek: Relationele databases en SQL downloaden van 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

4 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

5 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

6 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

7 Relationele databases: structuur
Hoofdstuk 1: Relationele databases: structuur 7

8 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

9 Applicatie: Toetjesboek
(applicatie bij Firebird-database) bij: Relationele databases en SQL ©Mattic b.v. 9

10 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

11 Receptwindow in applicatie (schematisch)
bij: Relationele databases en SQL ©Mattic b.v. 11

12 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

13 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

14 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

15 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

16 ‘Omkering’ van herhalende groep
‘gerechten’ als herhalende groep bij producten! bij: Relationele databases en SQL ©Mattic b.v. 16

17 Elimineren herhalende groep
bij: Relationele databases en SQL ©Mattic b.v.

18 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

19 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

20 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

21 Databasestructuur: strokendiagram
bij: Relationele databases en SQL ©Mattic b.v. 21

22 ‘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

23 Informatie als verwoording van gegevens
vier ‘informatie- atomen’: Atomaire informatie bij: Relationele databases en SQL ©Mattic b.v. 23

24 Relationele databases: regels
Hoofdstuk 2: Relationele databases: regels 24

25 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

26 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

27 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

28 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

29 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

30 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

31 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

32 bij: Relationele databases en SQL ©Mattic b.v.
Primaire ‘sloten’ ? bij: Relationele databases en SQL ©Mattic b.v. 32

33 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

34 Cardinaliteitsregels
Je leest de cardinaliteit aan de andere kant van het lijntje ! bij: Relationele databases en SQL ©Mattic b.v. 34

35 (Groot)ouder-(klein)kind
bij: Relationele databases en SQL ©Mattic b.v. 35

36 Ouder-kind: relatief t.o.v. verwijzing
Tekenconventie: ouder boven, kind onder, indien mogelijk bij: Relationele databases en SQL ©Mattic b.v. 36

37 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.

38 Alternatieve sleutels
primaire sleutel alternatieve sleutel bij: Relationele databases en SQL ©Mattic b.v. 38

39 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

40 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

41 bij: Relationele databases en SQL ©Mattic b.v.
Restricted delete bij: Relationele databases en SQL ©Mattic b.v. 41

42 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

43 bij: Relationele databases en SQL ©Mattic b.v.
Cascading delete bij: Relationele databases en SQL ©Mattic b.v. 43

44 bij: Relationele databases en SQL ©Mattic b.v.
Cascading update bij: Relationele databases en SQL ©Mattic b.v. 44

45 Update- en deleteregels in Toetjesboek-database
bij: Relationele databases en SQL ©Mattic b.v. 45

46 Samengestelde sleutel
bij: Relationele databases en SQL ©Mattic b.v. 46

47 Recursieve verwijzing
bij: Relationele databases en SQL ©Mattic b.v. 47

48 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

49 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

50 Niet-sleutelverwijzing
bij: Relationele databases en SQL ©Mattic b.v. 50

51 De OpenSchool-database
bij: Relationele databases en SQL ©Mattic b.v. 51

52 Communiceren met een relationele databases
Hoofdstuk 3: Communiceren met een relationele databases 52

53 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

54 Nogmaals: Toetjesboek (eindgebruikersapplicatie)
bij: Relationele databases en SQL ©Mattic b.v. 54

55 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

56 bij: Relationele databases en SQL ©Mattic b.v.
56

57 bij: Relationele databases en SQL ©Mattic b.v.
Een SQL-select query select naam, energiePP from Gerecht where bereidingstijd < order by energiePP 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

58 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

59 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

60 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

61 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

62 bij: Relationele databases en SQL ©Mattic b.v.
Delete Voorbeeld: verwijder het gerecht ‘banaan’. Oplossing: delete from Product 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

63 bij: Relationele databases en SQL ©Mattic b.v.
Update Voorbeeld: wijzig de energie per eenheid van goudrenetten in 550. Oplossing: update Product set energiePE = 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

64 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

65 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.

66 Hoofdstuk 4: Nulls 66

67 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

68 De OpenSchool-database
bij: Relationele databases en SQL ©Mattic b.v. 68

69 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

70 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

71 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

72 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

73 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

74 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

75 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

76 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

77 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

78 Prioriteit operatoren
1. not and 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

79 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

80 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

81 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

82 Hoofdstuk 5: Normalisatie 82

83 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

84 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

85 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

86 Van niet-genormaliseerd naar 1NV (1)
‘afsplitsen’ herhalende groep bij: Relationele databases en SQL ©Mattic b.v. 86

87 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

88 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

89 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

90 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

91 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

92 Overtredingen van 2NV en 3NV
bij: Relationele databases en SQL ©Mattic b.v. 92

93 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

94 Toegepast op voorbeeld
1NV / niet-2NV na afsplitsen FA: 2NV bij: Relationele databases en SQL ©Mattic b.v. 94

95 Transformatie: van 2NV/niet-3NV naar 3NV
bij: Relationele databases en SQL ©Mattic b.v. 95

96 Toegepast op voorbeeld
2NV / niet-3NV na afsplitsen FA: 3NV geen redundantie meer! bij: Relationele databases en SQL ©Mattic b.v. 96

97 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

98 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

99 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

100 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

101 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

102 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

103 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

104 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

105 Afsplitsen ‘binnenste’ herhalende groep
1NV ! bij: Relationele databases en SQL ©Mattic b.v. 105

106 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

107 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

108 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

109 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

110 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

111 Informatie uit één tabel
Hoofdstuk 6: Informatie uit één tabel 111

112 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

113 bij: Relationele databases en SQL ©Mattic b.v.
OpenSchool bij: Relationele databases en SQL ©Mattic b.v. 113

114 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 Discrete wiskunde Databases Informatiemodelleren Semantic web bij: Relationele databases en SQL ©Mattic b.v. 114

115 bij: Relationele databases en SQL ©Mattic b.v.
Projecties: distinct Vergelijk: select uren, credits from Cursus Resultaat: UREN CREDITS ========= ======= select distinct uren, credits from Cursus Resultaat: UREN CREDITS ========= ======= 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

116 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

117 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

118 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

119 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

120 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

121 bij: Relationele databases en SQL ©Mattic b.v.
Selecties: where Let op: kan verwarrend zijn select code, naam, credits : projectie from Cursus : brontabel where examinator = ‘DAT’ : selectie bij: Relationele databases en SQL ©Mattic b.v. 121

122 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 jan-2012 <NULL> J 4 DB feb-2012 <NULL> N 1 IM jun-2012 <NULL> N 3 II jan-2012 <NULL> <NULL> 1 DW jan N 2 IM jan N 1 II jan N 1 DB mrt N asc (klimmend ordenen) mag worden weggelaten. nulls voorop! (databasespecifiek) dalend ordenen: desc bij: Relationele databases en SQL ©Mattic b.v. 122

123 Verzamelingsoperatoren
Wiskundige verzamelingsfuncties op twee (rij)verzamelingen A en B: bij: Relationele databases en SQL ©Mattic b.v. 123

124 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 DB 1 DW 2 IM 2 IM 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

125 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 apr-2012 eerste poging 1 DB jun-2012 herkansing 1 DW apr-2012 eerste poging 1 II apr-2012 eerste poging 2 IM apr-2012 eerste poging 2 IM jun-2012 herkansing 4 DB jun-2012 eerste poging bij: Relationele databases en SQL ©Mattic b.v. 125

126 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

127 Informatie uit meerdere tabellen: joins
Hoofdstuk 7: Informatie uit meerdere tabellen: joins 127

128 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

129 bij: Relationele databases en SQL ©Mattic b.v.
OpenSchool bij: Relationele databases en SQL ©Mattic b.v. 129

130 Inner join van Student en Docent
join = verbrede tabel (via verwijzing) bij: Relationele databases en SQL ©Mattic b.v. 130

131 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

132 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

133 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

134 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

135 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

136 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

137 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

138 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

139 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

140 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

141 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 Berk 2 Tack COD E.Codd Bos BAC C.Bachman <NULL> <NULL> Kan niet in SQL! bij: Relationele databases en SQL ©Mattic b.v. 141

142 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 Berk DAT C.Date Tack COD E.Codd Bos BAC C.Bachman <NULL> <NULL> ACR NAAM STUDENTEN--- (NR NAAM ) DAT C.Date Berk 2 Tack COD E.Codd Bos BAC C.Bachman <NULL> <NULL> genormaliseerde versie van gevraagd overzicht bij: Relationele databases en SQL ©Mattic b.v. 142

143 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

144 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

145 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

146 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

147 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

148 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

149 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

150 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

151 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

152 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

153 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 BAC II jan N II Inleiding informatica BAC II jan-2012 <NULL> J II Inleiding informatica BAC II jan-2012 <NULL> <NULL> II Inleiding informatica BAC II jan-2012 <NULL> J DW Discrete wiskunde DAT DW jan N DW Discrete wiskunde DAT DW jan-2012 <NULL> J DB Databases COD DB mrt N DB Databases COD DB feb-2012 <NULL> N IM Informatiemodelleren DAT IM jun-2012 <NULL> N IM Informatiemodelleren DAT IM jan N SW Semantic web <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

154 Statistische informatie
Hoofdstuk 8: Statistische informatie 154

155 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

156 bij: Relationele databases en SQL ©Mattic b.v.
OpenSchool bij: Relationele databases en SQL ©Mattic b.v. 156

157 Statistische functies
Hoeveel inschrijvingen zijn er voor de cursus met code II? select count(*) aantal from Inschrijving where cursus = 'II' één statistische waarde over hele tabel (één groep) Resultaat: AANTAL ========= 4 bij: Relationele databases en SQL ©Mattic b.v. 157

158 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

159 bij: Relationele databases en SQL ©Mattic b.v.
Groeperen Aantal inschrijvingen per cursus: select cursus, count(*) aantal -- 3 from Inschrijving group by cursus tabel Inschrijving wordt opgedeeld in groepen van rijen: - per cursus één groep; - één statistische waarde per groep (= per cursus) Resultaat: CURSUS AANTAL ====== ========= DB DW II IM bij: Relationele databases en SQL ©Mattic b.v. 159

160 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 1 DW 1 II 2 IM 4 DB bij: Relationele databases en SQL ©Mattic b.v. 160

161 Voorwaarden aan groepen: having
Per cursus aantal inschrijvingen zonder vrijstelling. Beperken tot cursussen waar- voor dat aantal tenminste 2 is: Resultaat: CURSUS AANTAL ====== ========= DB IM select cursus, count(*) aantal -- 5 from Inschrijving where vrijstelling = 'N' group by cursus having count(*) >= bij: Relationele databases en SQL ©Mattic b.v. 161

162 Groeperen als denormaliseren (1)
Geef voor elke cursus met vrijstelling = ‘ N’: cursuscode, aantal inschrijvingen en gemiddelde cijfer. Oplossing: select cursus, count(*) aantal, avg(cijfer) gemiddelde_cijfer -- from Inschrijving where vrijstelling = ‘N’ group by cursus Eindresultaat (na stap 4): CURSUS AANTAL GEMIDDELDE_CIJFER ====== ========= ================= DB DW II IM bij: Relationele databases en SQL ©Mattic b.v. 162

163 Groeperen als denormaliseren (2)
Na stap 2: select … from Inschrijving where vrijstelling = ‘N’ is het tussenresultaat: STUDENT CURSUS DATUM CIJFER VRIJSTELLING ========= ====== =========== ====== ============ 1 II jan N 1 DW jan N 1 DB mrt N 1 IM jun-2012 <NULL> N 2 IM jan N 4 DB feb-2012 <NULL> N In stap 3 gaan we dit groeperen op kolom cursus bij: Relationele databases en SQL ©Mattic b.v. 163

164 Groeperen als denormaliseren (3)
Bij stap 3 – het groeperen op cursus – wordt een herhalende groep gemaakt: select … from Inschrijving where vrijstelling = ‘N’ group by cursus STUDENT CURSUS DATUM CIJFER VRIJSTELLING ========= ====== =========== ====== ============ 1 DB mrt N feb-2012 <NULL> N 1 DW jan N 1 II jan N 1 IM jun-2012 <NULL> N jan N Dit is tabel met vier rijen en twee kolommen, waarvan één een herhalende groep! bij: Relationele databases en SQL ©Mattic b.v. 164

165 Groeperen als denormaliseren (4)
Nog duidelijker wanneer we kolom cursus voorop zetten: CURSUS STUDENT DATUM CIJFER VRIJSTELLING ====== ========= =========== ====== ============ DB mrt N 4 29-feb-2012 <NULL> N DW jan N II jan N IM jun-2012 <NULL> N 2 26-jan N voor elke groep: count(*), avg(cijfer), Zo ontstaat het eindresultaat: CURSUS AANTAL GEMIDDELDE_CIJFER ====== ========= ================= DB DW II IM bij: Relationele databases en SQL ©Mattic b.v. 165

166 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

167 Starttabel en navigatierichting bij statistische query
bij: Relationele databases en SQL ©Mattic b.v. 167

168 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

169 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

170 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

171 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 DW Discrete wiskunde II Inleiding informatica IM Informatiemodelleren SW Semantic web Waarom een 1? Hoe op te lossen? bij: Relationele databases en SQL ©Mattic b.v. 171

172 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(*)) bij: Relationele databases en SQL ©Mattic b.v. 172

173 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

174 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

175 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

176 Hoofdstuk 9: Subselects en views 176

177 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

178 bij: Relationele databases en SQL ©Mattic b.v.
OpenSchool bij: Relationele databases en SQL ©Mattic b.v. 178

179 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

180 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

181 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

182 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

183 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

184 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

185 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

186 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

187 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

188 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

189 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

190 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

191 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

192 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

193 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

194 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

195 Wijzigen van een database-inhoud
Hoofdstuk 10: Wijzigen van een database-inhoud 195

196 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

197 OpenSchool

198 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

199 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

200 Transactie afsluiten met commit(moment) of rollback
transactie afgesloten met commitmoment: transactie afgesloten met rollback: bij: Relationele databases en SQL ©Mattic b.v. 200

201 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

202 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

203 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

204 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

205 Het update-statement: poging tot wijzigen
Voorbeeld eenvoudige update: update Cursus set uren = 140, credits = where code = 'DW' 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

206 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

207 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 DW Discrete wiskunde DB Databases IM Informatiemodelleren SW Semantic web (ongecorreleerde update) verklaring? bij: Relationele databases en SQL ©Mattic b.v. 207

208 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


Download ppt "Relationele databases en SQL"

Verwante presentaties


Ads door Google