SQL – deel 2 Katrien Verbert [email protected]
Inhoud van deze les
• Vervolg SQL: geavanceerde concepten en extra voorbeeld
• JDBC en embedded SQL
2
• Basisvorm van een vraag (query):
opvragingen (queries) in SQL
SELECT <a$ributen lijst> FROM <tabellen lijst> WHERE <condi3es> ;
3
voorbeeld
• Q_0: geef de geboortedatum en het adres van werknemer John B. Smith
Bdate Address ---------- ------------------------ 1965-01-09 731 Fondren, Houston, TX!
SELECT Bdate, Address FROM EMPLOYEE WHERE Fname='John' AND Minit='B' AND Lname='Smith’ ;!
• Q1B: geef naam en adres van alle werknemers die voor het "research" departement werken
SELECT E.Fname, E.Lname, E.Address FROM EMPLOYEE E, DEPARTMENT D WHERE D.Dname = 'Research' AND D.Dnumber = E.Dno ;!
5
geneste queries
• geneste queries – sommige queries vereisen ophalen van bestaande waarden en
het gebruik ervan in voorwaarden; – dat kan dikwijls op eenvoudige wijze geformuleerd worden met
geneste queries.
• IN operator in conditie : – test of tupel ∈ verzameling – verzameling kan zelf door SQL-query bekomen zijn
• → geneste queries
6
SELECT DISTINCT Pnumber FROM PROJECT WHERE Pnumber IN
(SELECT Pnumber FROM PROJECT, DEPARTMENT, EMPLOYEE WHERE Dnum = Dnumber AND Mgr_ssn = Ssn AND Lname = 'Smith') OR Pnumber IN
(SELECT Pno FROM WORKS_ON, EMPLOYEE WHERE Essn = Ssn AND Lname = 'Smith') ;
voorbeeld
– Q 4A: geef alle projecten waarbij Smith betrokken is als manager van het controlerend departement of waaraan hij meewerkt
7
8
9
SELECT DISTINCT Essn FROM WORKS_ON WHERE (Pno, Hours) IN (SELECT Pno, Hours FROM WORKS_ON WHERE Ssn = '123456789') ;
IN operator met tupel i.p.v. enkelvoudige waarde • tupel moet vergelijkbaar zijn met een element van de
verzameling • vb:
– selecteer de ssn’s van alle werknemers die met dezelfde combinatie (project, aantal uren) werken op om het even welk project waarop de werknemer ssn = ‘123456789’ werkt
10
SELECT E.Fname, E.Lname FROM EMPLOYEE AS E , DEPENDENT AS D WHERE E.Ssn = D.Essn AND E.Sex = D.Sex AND E.Fname = D.Dependent_name ;
• geef de naam van elke werknemer die een persoon ten laste heeft met dezelfde voornaam en hetzelfde geslacht als de werknemer
SELECT E.Fname, E.Lname FROM EMPLOYEE AS E WHERE E.Ssn IN (SELECT ESSN
FROM DEPENDENT AS D WHERE D.Essn AND E.Sex = D.Sex
AND E.Fname = D.Dependent_name) ;
Kan dit ook zonder geneste query?
andere vergelijkingsoperatoren • >, >=, <, <=, <> • combinatie met ANY (of SOME)
– v > ANY s : er bestaat een element e van s waarvoor v > e – = ANY is equivalent met IN
• combinatie met ALL – v > ALL s : voor alle elementen e van s geldt v >e
12
SELECT Lname, Fname FROM EMPLOYEE WHERE Salary > ALL (SELECT Salary FROM EMPLOYEE WHERE Dno = 5) ;
voorbeeld • bepaal de namen van alle werknemers waarvan het
salaris groter is dan de salarissen van alle werknemers van departement 5
13
SELECT E.Fname, E.Lname FROM EMPLOYEE AS E WHERE E.Ssn IN ( SELECT Essn FROM DEPENDENT WHERE Sex = E.Sex AND E.Fname = Dependent_name) ;!
oplossen van dubbelzinnigheid in geneste queries • verscheidene niveaus van innesteling zijn mogelijk
• indien attributen met dezelfde naam voorkomen in buitenste en binnenste query: – een referentie verwijst dan naar de binnenste geneste query – om naar een andere relatie te verwijzen moet de attribuutnaam
gekwalificeerd worden
14
SELECT Fname, Lname FROM EMPLOYEE WHERE ( ( SELECT Pno FROM WORKS_ON WHERE Ssn = Essn ) CONTAINS ( SELECT Pnumber FROM PROJECT WHERE Dnum = 5) ) ;
CONTAINS
• CONTAINS: "... heeft als deelverzameling ... " • vgl. met deling
– vb: geef de naam van elke werknemer die werkt op alle projecten gecontroleerd door departement nummer 5
15
16
17
SELECT E.Fname, E.Lname FROM EMPLOYEE AS E WHERE EXISTS (SELECT * FROM DEPENDENT WHERE E.Ssn = Essn AND E.Fname = Dependent_name) ;
EXISTS functie in SQL
• controleert of verzameling leeg is of niet • geeft TRUE indien er ten minste één element is, zoniet
FALSE
– Q 16 B: geef de naam van elke werknemer die een persoon ten laste heeft met dezelfde voornaam als de werknemer
18
NOT EXISTS
• geeft TRUE als de verzameling leeg is
• Q 6: geef de namen van de werknemers die geen personen ten laste hebben
SELECT E.Fname, E.Lname FROM EMPLOYEE AS E WHERE NOT EXISTS (SELECT * FROM DEPENDENT WHERE E.Ssn = Essn) ;
19
SELECT Fname, Lname FROM EMPLOYEE WHERE EXISTS ( SELECT * FROM DEPENDENT WHERE Ssn = Essn) AND EXISTS ( SELECT * FROM DEPARTMENT WHERE Ssn = Mgr_ssn) ;!
Kan dit ook met 1 geneste query / zonder geneste query?
– Q 7: Geef de namen van de managers die tenminste één persoon ten laste hebben
20
SELECT Fname, Lname FROM EMPLOYEE E WHERE NOT EXISTS (SELECT * FROM WORKS_ON B WHERE B.Pno IN (SELECT Pnumber FROM PROJECT WHERE Dnum = 5) AND NOT EXISTS (SELECT * FROM WORKS_ON C WHERE C.Essn = E.Ssn AND C.Pno = B.Pno) ) ;
• CONTAINS kan ook herschreven worden met NOT EXISTS • Q 3 B herformulering:
– geef alle werknemers waarvoor er geen project bestaat gecontroleerd door departement 5 waarop de werknemer niet werkt
NOT EXISTS
22
23
SELECT DISTINCT Essn FROM WORKS_ON WHERE Pno IN (1,2,3) ;!
expliciete verzamelingen
• verzameling constanten : – vb. (1,2,3)
• zoek de social security numbers of alle werknemers die werken op projecten nummer 1, 2 of 3
24
SELECT E.Lname AS Employee_name S.Lname AS Supervisor_Name FROM EMPLOYEE AS E, EMPLOYEE AS S WHERE E.Super_ssn = S.Ssn ;
hernoeming van attributen en tabellen met AS • Q 8 A
– geef de familienaam van elke werknemer met de familienaam van zijn/haar supervisor
25
joins
• JOIN operaties kunnen expliciet opgegeven worden – verhoogt de duidelijkheid – join condities gescheiden van selectiecondities
• FROM <tabel1> <jointype> <tabel2> ON <conditie> – inwendige join: [ INNER ] JOIN – uitwendig: { LEFT | RIGHT | FULL } [ OUTER ] JOIN – natuurlijke : NATURAL JOIN
26
voorbeeld
• Q 1 A – geef naam en adres van alle werknemers die voor het
“Research” departement werken
SELECT Fname, Lname, Address FROM (EMPLOYEE JOIN DEPARTMENT ON Dno = Dnumber) WHERE Dname = 'Research’ ;!
SELECT Fname, Lname, Address FROM ( EMPLOYEE NATURAL JOIN ( DEPARTMENT AS DEPT (Dname, Dno, Mssn, Msdate) ) ) WHERE Dname = 'Research’ ;
27
voorbeeld
• Q 8 B – geef de familienaam van elke werknemer met de familienaam van zijn/
haar supervisor
SELECT E.Lname AS Employee_name, S.Lname AS Supervisor_name FROM (EMPLOYEE AS E LEFT OUTER JOIN EMPLOYEE AS S ON E.Super_ssn = S.Ssn) ;
28
SELECT SUM(Salary), MAX(Salary), MIN(Salary), AVG(Salary) FROM EMPLOYEE;
aggregaatfuncties
• Ingebouwde functies: – COUNT, SUM, MAX, MIN, AVG
• voorbeeld: zoek som, maximum, minimum en gemiddelde van alle salarissen
29
SELECT DNO, COUNT(*), AVG(Salary) FROM EMPLOYEE GROUP BY DNO ;
groepering
• Groeperen van tupels : GROUP BY – aggregaatfuncties worden voor elke groep afzonderlijk toegepast
• voorbeeld: geef voor elk departement het nummer, het aantal werknemers en het gemiddelde salaris
30
• geef voor elk project nr, naam en aantal mensen die eraan werken
• .. enkel voor die projecten waar meer dan 2 mensen aan werken : met HAVING
SELECT Pnumber, Pname, COUNT(*) FROM PROJECT, WORKS_ON WHERE Pnumber = Pno GROUP BY Pnumber, Pname ;!
SELECT Pnumber, Pname, COUNT(*) FROM PROJECT, WORKS_ON WHERE Pnumber = Pno GROUP BY Pnumber, Pname HAVING COUNT(*) > 2 ;
31
SELECT Pnumber, Pname, COUNT(*) FROM PROJECT, WORKS_ON, EMPLOYEE WHERE Pnumber = Pno AND Ssn = Essn
AND Dno = 5 GROUP BY Pnumber, Pname ;
• geef voor elk project, het projectnummer, de projectnaam, en het aantal werknemers van departement 5 die op dat project werken
32
SELECT Dname, COUNT(*) FROM DEPARTMENT, EMPLOYEE WHERE Dnumber = Dno AND Salary > 40 000 GROUP BY Dname HAVING COUNT(*) > 5 ;!
oppassen met condities
• WHERE selecteert tupels vóór groepering • HAVING selecteert achteraf groepen • voorbeeld:
– geef voor elk departement met minstens 5 werknemers, de naam van het departement, het totaal aantal werknemers met salaris > 40 000 in dat departement
– Foute formulering: (wat is er fout aan?)
SELECT Dname, COUNT(*) FROM DEPARTMENT, EMPLOYEE WHERE Dnumber = Dno AND Salary > 40 000 AND Dno IN (SELECT Dno FROM EMPLOYEE GROUP BY Dno HAVING COUNT(*) > 5) GROUP BY Dname ;
• Correcte formulering: – Geef voor elk departement met minstens 5 werknemers het
totaal aantal werknemers met salaris > 40 000 in dat departement
34
algemene vorm van SQL-queries
– SELECT: op te halen attributen / functies – FROM: benodigde tabellen – WHERE: voorwaarden op tupels – GROUP BY: groepering (voor aggregaatfuncties) – HAVING: voorwaarden op gevormde groepen – ORDER: volgorde voor tonen van resultaat
SELECT < a$ributen-‐ en func3e-‐lijst > FROM < tabellenlijst > [ WHERE < voorwaarde > ] [ GROUP BY < groeperingsa$ributen > ] [ HAVING < groepvoorwaarde > ] [ ORDER BY < a$ributenlijst > ] ;
35
views in SQL
• “view" = afgeleide relatie – tupels worden niet expliciet opgeslagen – maar worden berekend uit andere relaties (= de definiërende
tabellen van de view)
36
• sytax CREATE VIEW <viewname> [ < lijst van attribuutnamen> ] AS <query>
CREATE VIEW WORKS_ON1 AS SELECT Fname, Lname, Pname, Hours FROM EMPLOYEE, PROJECT, WORKS_ON WHERE Ssn = Essn AND Pno = Pnumber ;!
CREATE VIEW DEPT_INFO(Dept_name,No_of_emps,Total_sal) AS SELECT Dname, COUNT(*), SUM(Salary) FROM DEPARTMENT, EMPLOYEE WHERE Dnumber = Dno GROUP BY Dname ;!
specificeren van een view
V1
37
gebruik van views
• queries op view: zoals bij gewone tabellen
• Voordelen van views?
SELECT Fname, Lname FROM WORKS_ON1 WHERE Pname = ‘ProductX’ ;
38
• eenvoudiger formulering van queries • beveiligingsmechanisme
• gebruiker zicht op deel van gegevensbank geven • vs. nieuwe tabel (cf. DEPT_INFO):
• geen redundantie • steeds up-to-date
weglaten van view
• DROP VIEW (cf. gewone tabel) – voorbeeld:
– geen verwijdering van tupels
DROP VIEW WORKS_ON1;
39
implementatie van views
• twee benaderingen: – query modification:
• query op view wordt omgevormd tot query op onderliggende tabellen; • nadeel: kan tot complexe en tijdsintensieve queries leiden
– view materialization: • tijdelijke creatie van de afgeleide (view) tabel wanneer ze voor het eerst in
een query gebruikt wordt; • vereist ‘incremental update’: aanpassing van de afgeleide tabel wanneer
basistabellen gewijzigd worden; • afgeleide tabel wordt automatisch weggelaten als ze een tijd niet meer
gebruikt wordt
40
voorbeeld van query modification
– de query QV1 op view WORKS_ON1
– wordt omgevormd tot
SELECT Fname, Lname FROM WORKS_ON1 WHERE Pname = ‘ProductX’ ;
SELECT Fname, Lname FROM EMPLOYEE, PROJECT, WORKS_ON WHERE Ssn = Essn AND Pno = Pnumber
AND Pname = ‘ProductX’ ;
41
wijzigen van view
• view is afgeleid uit andere relaties • ⇒ wijziging moet doorgegeven worden aan andere relaties • niet steeds mogelijk op eenduidige manier!
42
wijzigen van view
• View ← 1 basisrelatie: – aanpassing aan view → aanpassing aan basisrelatie
• View ← join van meerdere basisrelaties: – welke relaties aanpassen?
43
UPDATE WORKS_ON1 SET Pname = 'ProductY' WHERE Lname = 'Smith' AND Fname = 'John' AND Pname = 'ProductX’ ;
voorbeeld
• Wijzig PNAME van John Smith in WORKS_ON1 van 'ProductX' naar 'ProductY’
• Hoe de wijziging van productnaam doorgeven aan basisrelaties? – Is het project van naam veranderd? – Of werkt John Smith nu aan een ander project, nl. ProductY
i.p.v. ProductX ?
44
UPDATE PROJECT SET Pname = 'ProductY' WHERE Pname = 'ProductX’ ;!
UPDATE WORKS_ON SET Pno = (SELECT Pnumber FROM PROJECT WHERE Name = 'ProductY') WHERE Essn = (SELECT Ssn FROM EMPLOYEE WHERE Lname = 'Smith' AND Fname = 'John') AND PNO IN (SELECT Pnumber FROM PROJECT WHERE Pname = 'ProductX') ;
UPDATE DEPT_INFO SET TOTAL_SAL=100000 WHERE DNAME='Research’ ;!
sommige aanpassingen zijn zinloos:
45
wijzigen van views: algemeen
• een view afgeleid uit 1 tabel kan aangepast worden als de view een primaire sleutel of kandidaatsleutel van die tabel bevat (→ te wijzigen tupel is eenduidig bepaald)
• een view afgeleid uit meerdere tabellen is meestal niet aanpasbaar – indien meerdere aanpassingen mogelijk zijn, moet er een
procedure zijn om hieruit te kiezen, b.v.: • gebruiker vragen een keuze te maken
– DBMS meest waarschijnlijke laten kiezen
• resultaten van aggregaatfuncties kunnen niet aangepast worden
46
ASSERTIONS
ter herinnering
• restricties op tabellen • restricties op attribuutwaarden
48
restricties op tabellen
• primaire sleutel: PRIMARY KEY <attrlist> • alternatieve sleutel: UNIQUE <attrlist>
è worden nagekeken bij toevoegen of wijzigen van tupels
• verwijssleutel: FOREIGN KEY <attrlist> REFERENCES <table><attrlist>
è wordt nagekeken bij toevoegen of wijzigen van tupels in tabel è wordt nagekeken bij verwijderen of wijzigen van tupels in verwijzende tabel
49
referentiële integriteit
• Dno in EMPLOYEE verwijst altijd naar een bestaand dnumber in DEPARTMENT
primary key foreign key
51
referentiële integriteit
• Dno in EMPLOYEE verwijst altijd naar een bestaand dnumber in DEPARTMENT
primary key foreign key
6 6 6
restricties op attribuut
• NOT NULL (automatisch voor primaire sleutels) • DEFAULT <value> • CHECK (voorwaarde)
Dnumber INT NOT NULL CHECK (Dnumber > 0 AND Dnumber < 21);
53
è worden nagekeken bij toevoegen of wijzigen van attribuutwaarden
algemene restricties specificeren
• andere restricties dan sleutel-, entiteits- en referentiële restricties opgeven: ASSERTION
• algemene vorm:
CREATE ASSERTION <name> CHECK <cond>
54
CREATE ASSERTION SALARY_CONSTRAINT CHECK ( NOT EXISTS ( SELECT * FROM EMPLOYEE E, EMPLOYEE M, DEPARTMENT D WHERE E.Salary > M.Salary AND E.Dno = D.Dnumber AND D.Mgr_ssn = M.Ssn) ) ;!
voorbeeld
– salaris van werknemer <= salaris van manager van dept. waarvoor werknemer werkt
55
werking • bij creatie van een ASSERTION, wordt gecontroleerd of eraan voldaan is • elke latere wijziging in de gegevensbank:
– slechts toegelaten indien aan de ASSERTION voldaan is – dit kan veel extra werk vereisen!
• Voorbeeld: er moeten minstens drie werknemers per afdeling zijn.
CREATE ASSERTION NIET_MINDER_DAN_3 AS CHECK (NOT EXISTS (SELECT e1.DNO FROM (SELECT DISTINCT DNO FROM EMPLOYEE e1 WHERE 3 > (SELECT count(*) FROM EMPLOYEE e2 WHERE e2.DNO = e1.DNO)));
56
CHECK-clausule
• kan ook bij – attribuut - definitie – CREATE DOMAIN gebruikt worden
• → domeinrestricties • voorbeeld:
– departementsnummer kan slechts een gehele waarde tussen 1 en 20 zijn:
CREATE DOMAIN D_NUM AS INTEGER CHECK (D_NUM > 0 AND D_NUM < 21) ;
DNUMBER INT NOT NULL CHECK (DNUMBER > 0 AND DNUMBER < 21);
57
verschil tussen CHECK clausule bij attribuut, domein of tupel en ASSERTION
• CHECK – wordt slechts gecontroleerd bij toevoegen of aanpassen van tupels,
slaat op attributen of tupels – kan dus efficiënter geïmplementeerd worden
• ASSERTION – is meer algemeen
58
andere mogelijkheden
• CREATE TRIGGER
• hierbij wordt de te nemen actie opgegeven wanneer niet aan de voorwaarde voldaan is
59
TRIGGERS
triggers
• een trigger bestaat uit 3 delen: • een event (bv. update van een attribuut) • een voorwaarde (bv. een query die nagekeken wordt) • een actie (delete, update, insert)
• syntax
CREATE TRIGGER <name> { BEFORE | AFTER } <event> ON <table> FOR EACH ROW WHEN (<cond>)
<ac3on>
61
voorbeeld
CREATE TRIGGER TotalSal1 AFTER INSERT ON EMPLOYEE FOR EACH ROW WHEN (NEW.DNO IS NOT NULL)
UPDATE DEPARTMENT SET TOTAL_SAL=TOTAL_SAL + NEW.SALARY WHERE DNO=NEW.DNO
62
elementen van triggers
• timing van uitvoering van de actie – before – after – instead of
• actie kan verwijzen naar oude of nieuwe toestand van de gegevensbank
• conditie wordt gespecificeerd in WHEN clausule
63