Download de presentatie
De presentatie wordt gedownload. Even geduld aub
GepubliceerdSimon Wauters Laatst gewijzigd meer dan 9 jaar geleden
1
Databases I (H.8) SQL Wiebren de Jonge Vrije Universiteit, Amsterdam versie 2003
2
Te behandelen querytalen relationele algebra domeincalculus tupelcalculus SQL
3
SQL meest gangbare querytaal relationele DBMSen aanvankelijk ontwikkeld vanuit IBM daarna: –1986: SQL1 (ANSI / ISO) –1992: SQL2 –inmiddels: SQL3 DDL + DML + VDL (in SQL1 ook enigszins SDL) DML gebaseerd op tupelcalculus en relationele algebra in dit college: DDL + DML + VDL van SQL2
4
Voorbeeld Database: Company DEPT D#NAMEBUDGET D1engineering500,000 D2sales200,000 DPD EMPE#NAME REL E#NAME BDATE D# E3Mary daughter E1John 1964-08-28 D1 E3Sue wife E2Joe 1968-04-04 D1 E4Suzie daughter E3Jack 1969-09-03 D1 E4Tom son E4Will 1971-03-21 D2 E4Mary wife E5Bridget 1972-01-22 D2
5
Create schema(DDL) CREATE SCHEMA Company AUTHORIZATION Martinc SQL schema (= DB schema) beschrijft o.a.: tables, constraints, views en domains Idee: meerdere, gescheiden databases op dezelfde DBMS mogelijk (security, naming)
6
Create table (1/3)(DDL) CREATE TABLE DEPT (D#CHAR(2)NOT NULL, NAMEVARCHAR(15)NOT NULL, BUDGET INT, PRIMARY KEY (D#), UNIQUE (NAME)); N.B.: We nemen voor het gemak aan dat identifiers zoals D# en E# zijn toegestaan.
7
Create table (2/3)(DDL) CREATE TABLE EMP (E#CHAR(2) NOT NULL, NAMEVARCHAR(15)NOT NULL, BDATEDATE, D# CHAR(2)DEFAULT “D1”, PRIMARY KEY (E#), FOREIGN KEY (D#) REFERENCES DEPT (D#) ON DELETE SET NULL ON UPDATE CASCADE ); N.B.: andere opties bij FK: 1) SET DEFAULT 2) niets specificeren (=restricted)
8
Create table (3/3)(DDL) CREATE TABLE DPD (E#CHAR(2)NOT NULL, NAMEVARCHAR(15)NOT NULL, RELVARCHAR(15), PRIMARY KEY (E#, NAME), FOREIGN KEY (E#) REFERENCES EMP (E#) ON DELETE CASCADE ON UPDATE CASCADE );
9
Data types Enkele SQL data types: –INT, SMALLINT –FLOAT –DECIMAL(i, j) (met i significante cijfers waarvan j achter de komma) –CHAR(n) –VARCHAR(n) –DATE (b.v. formaat: ‘YYYY-MM-DD’) –TIME (b.v. formaat: ‘HH:MM:SS’) –TIMESTAMP (bevat datum, tijd en fracties van seconde)
10
Create domain(DDL) CREATE DOMAIN NAME_DOMAS VARCHAR(15); CREATE DOMAIN ENR_DOMAS CHAR(2); CREATE DOMAIN DNR_DOMAS CHAR(2); CREATE DOMAIN BDATE_DOMAS DATE; CREATE TABLE EMP (E#ENR_DOM NOT NULL, NAMENAME_DOM NOT NULL, BDATEBDATE_DOM, D# DNR_DOM, PRIMARY KEY (E#), FOREIGN KEY (D#) REFERENCES DEPT (D#) ON DELETE SET NULL ON UPDATE CASCADE);
11
Drop table(DDL) DROP TABLE DPD; DROP TABLE DEPT RESTRICT; DROP TABLE DEPT CASCADE; DROP SCHEMA Company CASCADE;
12
Alter table(DDL) Bijvoorbeeld: ALTER TABLE Company.DPD ADD BDATE BDATE_DOM; ALTER TABLE Company.DEPT DROP BUDGET; ALTER TABLE Company.EMP ALTER D# SET DEFAULT “D2”; N.B.: Ga er (ook) hierna steeds vanuit dat de gegeven wijzigings-acties niet zijn uitgevoerd op de Company DB !!
13
Insert(DML) INSERT INTO EMP VALUES ("E1", "John", '1964-08-28', "D1"); INSERT INTO EMP (E#, NAME, BDATE, D#) VALUES ("E1", "John", '1964-08-28', "D1"); INSERT INTO EMP (E#, NAME) VALUES ("E1", "John"); (D# wordt default “D1”, BDATE wordt NULL) INSERT INTO EMP (NAME, BDATE, D#) VALUES ("John", '1964-08-28', "D1"); (mag niet, want E# mag geen NULL zijn)
14
Update(DML) UPDATE DEPT SET BUDGET = 600000 WHERE NAME = “engineering”; UPDATE DEPT SET D# = “D3” WHERE D# = “D1”;
15
Delete(DML) DELETE FROM DPD WHERE E# = “E3” AND REL = “wife”; DELETE FROM EMP WHERE NAME = “Will”; DELETE FROM EMP;
16
Retrieval(DML) Algemene vorm SQL (retrieval-)query: SELECT [...] FROM [WHERE ] [GROUP BY [HAVING ] ] [ORDER BY ]; Hierbij staat [...] voor: [ALL/DISTINCT] Dus de mogelijkheden zijn: SELECT, SELECT ALL, SELECT DISTINCT (En er geldt: SELECT = SELECT ALL)
17
Voorbeeld query(DML) “Geef de naam en geboortedatum van de employees die in D2 werken” SELECTE.NAME, E.BDATE FROMEMP AS E WHERE E.D# = “D2”; alternatief 1:of zelfsalternatief 2: SELECT EMP.NAME, EMP.BDATESELECT NAME, BDATE FROM EMPFROM EMP WHERE EMP.D# = “D2”;WHERE D# = “D2”; dringend advies: gebruik altijd ‘qualifying’ van attributen en ‘aliasing’ t.b.v. expliciete tupelvariabelen
18
Vergelijk met tupelcalculus(DML) “Geef de namen en E#'s van employees die voor 1970 zijn geboren” SELECTE.NAME, E.E# FROMEMP AS E WHEREE.BDATE < “1970-01-01”; in tupelcalculus: { (e.name, e.E#) | EMP(e) e.bdate < “1970-01-01” }
19
Voorbeeld query(DML) “Geef alle informatie uit de EMP-tabel van de employees die in D2 werken” SELECT FROMEMP AS E WHERE E.D# = “D2”; “Geef de naam en geboortedatum van alle employees” SELECTE.NAME, E.BDATE FROMEMP AS E;
20
Voorbeeld query(DML) “Geef van elk department het D# en het budget in guldens” (er van uitgaande dat de budgetten in euro’s opgeslagen zijn) SELECTD.D#, D.BUDGET 2.20371 FROMDEPT AS D; “Geef de naam en geboortedatum van de employees die in september geboren zijn” SELECTE.NAME, E.BDATE FROMEMP AS E WHEREE.BDATE LIKE ‘____-09-__’;
21
Voorbeeld query(DML) “Geef alle namen van dependents” SELECTD.NAME FROMDPD AS D; NAME Mary Sue Suzie Tom Mary Dubbele tupels worden in SQL i.h.a. niet vanzelf verwijderd ! (wel bij set-operaties UNION, INTERSECT en EXCEPT)
22
Voorbeeld query(DML) “Geef alle verschillende namen van dependents” SELECT DISTINCTD.NAME FROMDPD AS D; NAME Sue Suzie Tom Mary
23
Voorbeeld query(DML) “Geef alle verschillende namen van dependents, in alfabetische volgorde” SELECTDISTINCT D.NAME FROMDPD AS D ORDER BYD.NAME; NAME Mary Sue Suzie Tom
24
Voorbeeld query(DML) “Geef het gemiddelde department-budget” SELECTAVG (D.BUDGET) FROMDEPT AS D “Geef voor ieder department met minstens één werknemer het D# en het aantal werknemers” SELECTE.D#, COUNT (E.E#) FROMEMP AS E GROUP BYE.D# N.B.: “met 1 werknemer” volgt uit feit dat je EMP gebruikt (en niet ook DEPT)
25
Toelichting EMP E#NAME BDATE D# E1John 1964-08-28 D1 voor D#=“D1”: E2Joe 1968-04-04 D1 COUNT(E#)=3 E3Jack 1969-09-03 D1 E4Will 1971-03-21 D2 voor D#=“D2”: E5Bridget 1972-01-22 D2 COUNT(E#)=2 dus resultaat:E.D#COUNT(E.E#) D13 D22
26
Voorbeeld query(DML) “Geef voor ieder department met meer dan 2 employees het D# en het aantal employees” SELECTE.D#, COUNT(E.E#) FROMEMP AS E GROUP BYE.D# HAVINGCOUNT(E.E#) > 2; N.B.: HAVING is, zeg maar, de ‘where-clause’ bij GROUP BY en ‘werkt’ op elke ‘group’
27
Toelichting EMP E#NAME BDATE D# E1John 1964-08-28 D1 voor D#=“D1”: E2Joe 1968-04-04 D1 COUNT(E#)=3 E3Jack 1969-09-03 D1 E4Will 1971-03-21 D2 voor D#=“D2”: E5Bridget 1972-01-22 D2 COUNT(E#)=2 dus resultaat:E.D#COUNT(E.E#) D13
28
Voorbeeld query(DML) “Geef voor ieder department met minstens één employee geboren voor 1970 het D# en het aantal employees geboren voor 1970” SELECTE.D#, COUNT(E.E#) FROMEMP AS E WHEREE.BDATE < ‘1970-01-01’ GROUP BYE.D#;
29
Toelichting Tussenresultaat na selectie (i.e. uitvoering van WHERE-clause): E#NAME BDATE D# E1John 1964-08-28 D1 D#=“D1”, E2Joe 1968-04-04 D1 COUNT(E#)=3 E3Jack 1969-09-03 D1 dus resultaat:E.D#COUNT(E.E#) D13
30
Algemene vorm SQL queries(DML) Algemene vorm SQL (retrieval-)query: SELECT [...] FROM [WHERE ] [GROUP BY [HAVING ] ] [ORDER BY ]; Evaluatie in volgorde FROM, WHERE, GROUP BY, HAVING, ORDER BY (en dan: SELECT, DISTINCT)
31
Voorbeeld query ( / )(DML) “Geef de namen en E#'s van employees die voor 1970 zijn geboren” SELECTE.NAME, E.E# FROMEMP AS E WHEREE.BDATE < “1970-01-01”; in tupelcalculus: { (e.name, e.E#) | EMP(e) e.bdate < “1970-01-01” }
32
Voorbeeld query ( )(DML) “Geef de namen van de dependents van Will” SELECTD.NAME FROMDPD AS D, EMP AS E WHERED.E# = E.E# AND E.NAME = “Will”; in tupelcalculus: { (d.name) | DPD(d) e (EMP(e) d.E# = e.E# e.name = “Will”) } In SQL geldt:elke ‘niet-vrije’ variabele is altijd (impliciet) existentieel (i.e. met ) gekwantificeerd !! Gevolg: soms ‘probleem’ met (want kan er niet vóór !! En géén )
33
Voorbeeld database SECRETARY NAME E# BDATE ADDRESS TSPEED Sue E1 1971-08-21 Singel 30 80 Mary E2 1968-12-18 Damrak 18 90 SALESMAN NAME E# BDATE ADDRESS LMT John E3 1969-08-08 Rokin 21 50000 Joe E4 1970-10-09 Nes 87 75000 ENGINEER NAME E# BDATE ADDRESS SPECIAL Jack E5 1972-02-02 NZVBW 13 electronics Jill E6 1971-01-01 NZABW 15 software
34
Voorbeeld query ( )(DML) “Geef voor iedere employee (= secretary, salesman of engineer) z’n E# en naam” (SELECTSEC.E#, SEC.NAME FROM SECRETARY AS SEC)in tupelcalculus: UNION{ (e.E#, e.name) | (SELECT SAL.E#, SAL.NAME SECRETARY(e) FROMSALESMAN AS SAL) SALESMAN(e) UNION ENGINEER(e) } (SELECT ENG.E#, ENG.NAME FROMENGINEER AS ENG);
35
Voorbeeld query ( )(DML) “Geef de E#'s en namen van de ongehuwde engineering- employees” Versie 1: (SELECT E.E#, E.NAME FROM EMP AS E, DEPT AS DPM WHERE E.D# = DPM.D# AND DPM.NAME = “engineering”) EXCEPT (SELECT E.E#, E.NAME FROM EMP AS E, DPD AS D WHERE E.E# = D.E# AND (D.REL = “husband” OR D.REL = “wife”);
36
Alternatief: versie 2(DML) “Geef de E#'s en namen van de ongehuwde engineering- employees” SELECTE.E#, E.NAME FROMEMP AS E WHEREE.D# IN (SELECTDPM.D# FROMDEPT AS DPM WHEREDPM.NAME = “engineering”) AND E.E# NOT IN (SELECTD.E# FROMDPD AS D WHERED.REL=“husband” OR D.REL=“wife”);
37
Alternatief: versie 3(DML) “Geef de E#'s en namen van de ongehuwde engineering- employees” SELECTE.E#, E.NAME FROMEMP AS E WHEREEXISTS (SELECT* FROMDEPT AS DPM WHEREDPM.NAME = “engineering” AND DPM.D# = E.D#) AND NOT EXISTS (SELECT* FROMDPD AS D WHERE(D.REL=“husband” OR D.REL=“wife”) AND D.E# = E.E# );
38
Vergelijk m.n. versie 3 met tupelcalculus SELECT E.E#, E.NAME FROM EMP AS E WHERE EXISTS (SELECT* FROMDEPT AS DPM WHEREDPM.NAME = “engineering” AND DPM.D# = E.D#) AND NOT EXISTS (SELECT* FROMDPD AS D WHERE(D.REL=“husband” OR D.REL=“wife”) AND D.E# = E.E#); { (e.name, e.E#) | EMP(e) dpm ( DEPT(dpm) dpm.name = “engineering” dpm.D# = e.D# ) d ( DPD(d) (d.rel = “husband” d.rel = “wife”) d.E# = e.E# ) }
39
Alternatief: versie 4(DML) “Geef de E#'s en namen van de ongehuwde engineering- employees” SELECTE.E#, E.NAME FROMEMP AS E, DEPT AS DPM WHEREDPM.NAME = “engineering” AND DPM.D# = E.D# AND NOT EXISTS (SELECTD.E# FROMDPD AS D WHERE(D.REL=“husband” OR D.REL=“wife”) AND D.E# = E.E#); ADVIES:probeer i.h.a. “platte” queries te formuleren en “nesting” te vermijden
40
Vergelijk versie 4 met tupelcalculus SELECTE.E#, E.NAME FROMEMP AS E, DEPT AS DPM WHEREDPM.NAME = “engineering” AND DPM.D# = E.D# AND NOT EXISTS (SELECTD.E# FROMDPD AS D WHERE(D.REL=“husband” OR D.REL=“wife”) AND D.E# = E.E#); { (e.name, e.E#) | EMP(e) dpm ( DEPT(dpm) dpm.name = “engineering” dpm.D# = e.D# ) d ( DPD(d) (d.rel = “husband” d.rel = “wife”) d.E# = e.E# ) }
41
Voorbeeld-DB PROJ J#NAME J1build-intranet J2market-research EMP_PROJ EMPE#J# E#NAME BDATE D# E2J1 E1John 28-08-1964 D1 E3J1 E2Joe 04-04-1968 D1 E3J2 E3Jack 03-09-1969 D1 E4J2 E4Will 21-03-1971 D2 E5J2 E5Bridget 22-01-1972 D2
42
Voorbeeld query ( )(DML) “Geef de E#’s van de employees die werken aan alle projecten” algebra: EMP_PROJ J# PROJ domeincalculus: { (e) | EMP_PROJ (E#: e) j ( PROJ(J#: j) EMP_PROJ(E#: e, J#: j) ) } tupelcalculus: { (e.E#) | EMP_PROJ(e) j ( PROJ(j) w (EMP_PROJ(w) w.E# = e.E# w.J# = j.J#)) } N.B.: bij de calculi nu EMP_PROJ(E#: e) resp. EMP_PROJ(e) gebruikt i.p.v. EMP(E#: e) resp. EMP(e) !! (Dat maakt vgl. met algebra eerlijker.)
43
Voorbeeld query ( )(DML) probleem: SQL heeft geen oplossing: herschrijf in query naar { (e.E#) | EMP_PROJ(e) j ( PROJ(j) w (EMP_PROJ(w) w.E# = e.E# w.J# = j.J#) ) } { (e.E#) | EMP_PROJ(e) j ( PROJ(j) w (EMP_PROJ(w) w.E# = e.E# w.J# = j.J#) ) } { (e.E#) | EMP_PROJ(e) j ( PROJ(j) w (EMP_PROJ(w) w.E# = e.E# w.J# = j.J#) ) }
44
Voorbeeld query ( )(DML) “Geef de E#'s van de employees die werken aan alle projecten” SELECTE.E# FROMEMP_PROJ AS E WHERENOT EXISTS (SELECT * FROM PROJ AS J WHERE NOT EXISTS (SELECT * FROM EMP_PROJ AS W WHERE W.E# = E.E# AND W.J# = J.J#) );
45
Voorbeeld complexe queries(DML) “Geef de namen en adressen van alle eventuele paren (d.w.z. personen van tegenovergesteld geslacht die binnen elkaars gewenste leeftijdscategorie vallen)” SELECTM.NAAM, M.ADRES, V.NAAM, V.ADRES FROMZOEKENDE AS M, ZOEKENDE AS V WHEREM.GESL = “M” AND V.GESL=“V” AND M.MINJ <= V.GJAAR AND V.GJAAR <= M.MAXJ AND V.MINJ <= M.GJAAR AND M.GJAAR <= V.MAXJ;
46
Voorbeeld complexe queries (null-waarden) ZOEKENDE NAAM ADRES GESL GJAARMINJ MAXJ Teun Nes 30 M null1950 1960 Wim Singel 23 M 19571950 1960 Sjon Damstr 9 M 19751975 1980 Truus Amstel 80 V null1950 1960 Bep Rokin 42 V 19571950 1960 Anita NZVBW 18 V 19801975 1980 Kan Teun aan Bep gekoppeld worden? geldt (1950 <= null) AND (null <= 1960) ? geldt dan misschien ((1950 <= null) AND (null <= 1960)) ? Antwoord: 2x nee
47
SQL: null-waarden + 3-waardige logica SQL gebruikt driewaardige logica (true / false / unknown) rekenregels logica: t u = ut u = t u = u f u = ff u = u u u = uu u = u alle vergelijkingen met null (m.b.v. operator { , , , , , }) leveren unknown op !! (dus ook “null = null” levert unknown) alleen tupels waarvoor de expressie true is (en dus niet unknown of false) worden geselecteerd speciale operatoren IS en IS NOT (voor testen gelijkheid met null)
48
Voorbeeld complexe queries (null-waarden) ZOEKENDE NAAM ADRES GESL GJAARMINJ MAXJ Teun Nes 30 M null1950 1960 Wim Singel 23 M 19571950 1960 Sjon Damstr 9 M 19751975 1980 Truus Amstel 80 V null1950 1960 Bep Rokin 42 V 19571950 1960 Anita NZVBW 18 V 19801975 1980 (geef de mannen en vrouwen (n+a) met hetzelfde geboortejaar) SELECTM.NAAM, M.ADRES, V.NAAM, V.ADRES FROMZOEKENDE AS M, ZOEKENDE AS V WHEREM.GESL = ‘M’ AND V.GESL = ‘V’ AND M.GJAAR = V.GJAAR;
49
Voorbeeld complexe queries (null-waarden) ZOEKENDE NAAM ADRES GESL GJAARMINJ MAXJ Teun Nes 30 M null1950 1960 Wim Singel 23 M 19571950 1960 Sjon Damstr 9 M 19751975 1980 Truus Amstel 80 V null1950 1960 Bep Rokin 42 V 19571950 1960 Anita NZVBW 18 V 19801975 1980 (geef de zoekenden (n+a) met een onbekend geboortejaar) SELECTZ.NAAM, Z.ADRES FROMZOEKENDE AS Z WHEREZ.GJAAR IS NULL;
50
Voorbeeld complexe queries (DML) DRAAITFAN_VAN STATIONARTIESTPERSOONARTIEST CountryCarpenters JanOP CountryParton PietMeeuwis NoordzeeHazes JoostBorsato NoordzeeBorsato JoostCarpenters NoordzeeMeeuwis Radio10MeeuwisLUISTERT_NAAR Radio10ElvisPERSOONSTATION Radio10Abba JanRadio10 PietNoordzee JoostRadio10 JoostNoordzee
51
Voorbeeld complexe queries(DML) “Geef de artiesten die gedraaid worden op de stations waar Joost naar luistert” SELECTD.ARTIEST FROMDRAAIT AS D, LUISTERT_NAAR AS L WHERED.STATION = L.STATION AND L.PERSOON = “Joost”; tupelcalculus: { (d.artiest) | DRAAIT(d) l (LUISTERT_NAAR(l) l.station = d.station l.persoon = “Joost”) }
52
Voorbeeld complexe queries(DML) “Geef de fans van artiesten die nergens gedraaid worden” SELECTF.PERSOON FROMFAN_VAN AS F WHERENOT EXISTS (SELECTD.STATION FROMDRAAIT AS D WHERED.ARTIEST = F.ARTIEST); tupelcalculus: { (f.persoon) | FAN_VAN(f) d (DRAAIT(d) d.artiest = f.artiest) }
53
Voorbeeld complexe queries(DML) “Geef de personen die tenminste naar ieder radiostation luisteren waar Piet ook naar luistert” (dus eventueel ook nog naar andere stations) leuke oefening voor thuis ??
54
Voorbeeld complexe queries(DML) “Geef de personen die tenminste naar ieder radiostation luisteren waar Piet ook naar luistert” SELECTL1.PERSOON FROMLUISTERT_NAAR AS L1 WHERENOT EXISTS (SELECTLPIET.STATION FROMLUISTERT_NAAR AS LPIET WHERELPIET.PERSOON = “PIET” AND NOT EXISTS (SELECT* FROMLUISTERT_NAAR AS L2 WHEREL2.PERSOON = L1.PERSOON AND L2.STATION = LPIET.STATION));
55
Views: zie ANSI/SPARC architectuur
56
Create view(VDL) SQL view: named, derived, virtual table (vgl. ANSI/SPARC) “Creëer een view met per department-name het aantal employees (als dat 1 is) ” CREATE VIEWDEPT_OVERVIEW (AFD, AANTAL) ASSELECT D.NAME, COUNT(E.E#) FROMDEPT AS D, EMP AS E WHERED.D# = E.D# GROUP BYD.NAME; View implementatie: query modification of view materialization Niet alle views (resp. attributen van views) zijn updatable
57
Constraints (1/2)(DDL) CREATE DOMAIN REL_DOMAIN AS VARCHAR(7) CHECK (REL_DOMAIN = “husband” OR REL_DOMAIN = “wife” OR REL_DOMAIN = “son” OR REL_DOMAIN = “daughter”); CREATE DOMAIN BUDGET_DOMAIN AS INT CHECK (BUDGET_DOMAIN >= 0 AND BUDGET_DOMAIN <= 1000000);
58
Constraints (2/2)(DDL) CREATE ASSERTION NO_EMPTY_DEPARTMENTS CHECK (NOT EXISTS (SELECT* FROMDEPT AS D WHERENOT EXISTS (SELECT* FROMEMP AS E WHEREE.D# = D.D#)));
Verwante presentaties
© 2024 SlidePlayer.nl Inc.
All rights reserved.