1. SQL – deel 2
Katrien Verbert
katrien.verbert@cs.kuleuven.be
2. Inhoud van deze les
• Vervolg SQL: geavanceerde concepten en extra
voorbeeld
• JDBC en embedded SQL
2
3. opvragingen (queries) in SQL
• Basisvorm van een vraag (query):
SELECT
<a$ributen
lijst>
FROM
<tabellen
lijst>
WHERE
<condi3es>
;
3
4. voorbeeld
• Q_0: geef de geboortedatum en het adres van
werknemer John B. Smith
SELECT
Bdate,
Address
FROM
EMPLOYEE
WHERE
Fname='John'
AND
Minit='B'
AND
Lname='Smith’
;!
Bdate Address
---------- ------------------------
1965-01-09 731 Fondren, Houston, TX!
5. • 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
6. 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
7. voorbeeld
– Q 4A: geef alle projecten waarbij Smith betrokken is als
manager van het controlerend departement of waaraan hij
meewerkt
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')
;
7
10. 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
SELECT
DISTINCT
Essn
FROM
WORKS_ON
WHERE
(Pno,
Hours)
IN
(SELECT
Pno,
Hours
FROM
WORKS_ON
WHERE
Ssn
=
'123456789')
;
10
11. • 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?
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
;
12. 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
13. voorbeeld
• bepaal de namen van alle werknemers waarvan het
salaris groter is dan de salarissen van alle werknemers
van departement 5
SELECT
Lname,
Fname
FROM
EMPLOYEE
WHERE
Salary
>
ALL
(SELECT
Salary
FROM
EMPLOYEE
WHERE
Dno
=
5)
;
13
14. 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
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)
;!
14
15. 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
SELECT
Fname,
Lname
FROM
EMPLOYEE
WHERE
(
(
SELECT
Pno
FROM
WORKS_ON
WHERE
Ssn
=
Essn
)
CONTAINS
(
SELECT
Pnumber
FROM
PROJECT
WHERE
Dnum
=
5)
)
;
15
18. 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
SELECT
E.Fname,
E.Lname
FROM
EMPLOYEE
AS
E
WHERE
EXISTS
(SELECT
*
FROM
DEPENDENT
WHERE
E.Ssn
=
Essn
AND
E.Fname
=
Dependent_name)
;
18
19. 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
20. – Q 7: Geef de namen van de managers die tenminste één
persoon ten laste hebben
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?
20
21. NOT EXISTS
• 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
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)
)
;
24. 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
SELECT
DISTINCT
Essn
FROM
WORKS_ON
WHERE
Pno
IN
(1,2,3)
;!
24
25. hernoeming van attributen en tabellen
met AS
• Q 8 A
– 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,
EMPLOYEE
AS
S
WHERE
E.Super_ssn
=
S.Ssn
;
25
26. 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
27. 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
28. 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
29. aggregaatfuncties
• Ingebouwde functies:
– COUNT, SUM, MAX, MIN, AVG
• voorbeeld: zoek som, maximum, minimum en
gemiddelde van alle salarissen
SELECT
SUM(Salary),
MAX(Salary),
MIN(Salary),
AVG(Salary)
FROM
EMPLOYEE;
29
30. 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
SELECT
DNO,
COUNT(*),
AVG(Salary)
FROM
EMPLOYEE
GROUP
BY
DNO
;
30
31. • geef voor elk project nr, naam en aantal mensen die
eraan werken
SELECT
Pnumber,
Pname,
COUNT(*)
FROM
PROJECT,
WORKS_ON
WHERE
Pnumber
=
Pno
GROUP
BY
Pnumber,
Pname
;!
• .. 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
HAVING
COUNT(*)
>
2
;
31
32. • geef voor elk project, het projectnummer, de projectnaam,
en het aantal werknemers van departement 5 die op dat
project werken
SELECT
Pnumber,
Pname,
COUNT(*)
FROM
PROJECT,
WORKS_ON,
EMPLOYEE
WHERE
Pnumber
=
Pno
AND
Ssn
=
Essn
AND
Dno
=
5
GROUP
BY
Pnumber,
Pname
;
32
33. 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
GROUP
BY
Dname
HAVING
COUNT(*)
>
5
;!
34. • Correcte formulering:
– Geef voor elk departement met minstens 5 werknemers het
totaal aantal werknemers met salaris > 40 000 in dat
departement
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
;
34
35. algemene vorm van SQL-queries
SELECT
<
a$ributen-‐
en
func3e-‐lijst
>
FROM
<
tabellenlijst
>
[
WHERE
<
voorwaarde
>
]
[
GROUP
BY
<
groeperingsa$ributen
>
]
[
HAVING
<
groepvoorwaarde
>
]
[
ORDER
BY
<
a$ributenlijst
>
]
;
– 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
35
36. 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
37. specificeren van een view
• sytax
CREATE VIEW <viewname> [ < lijst van attribuutnamen> ]
AS <query>
V1
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
;!
37
38. gebruik van views
• queries op view: zoals bij gewone tabellen
SELECT
Fname,
Lname
FROM
WORKS_ON1
WHERE
Pname
=
‘ProductX’
;
• Voordelen van views?
• eenvoudiger formulering van queries
• beveiligingsmechanisme
• gebruiker zicht op deel van gegevensbank geven
• vs. nieuwe tabel (cf. DEPT_INFO):
• geen redundantie
• steeds up-to-date
38
39. weglaten van view
• DROP VIEW (cf. gewone tabel)
– voorbeeld:
DROP
VIEW
WORKS_ON1;
– geen verwijdering van tupels
39
40. 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
41. voorbeeld van query modification
– de query QV1 op view WORKS_ON1
SELECT
Fname,
Lname
FROM
WORKS_ON1
WHERE
Pname
=
ProductX
;
– wordt omgevormd tot
SELECT
Fname,
Lname
FROM
EMPLOYEE,
PROJECT,
WORKS_ON
WHERE
Ssn
=
Essn
AND
Pno
=
Pnumber
AND
Pname
=
ProductX
;
41
42. wijzigen van view
• view is afgeleid uit andere relaties
• ⇒ wijziging moet doorgegeven worden aan andere relaties
• niet steeds mogelijk op eenduidige manier!
42
43. wijzigen van view
• View ← 1 basisrelatie:
– aanpassing aan view → aanpassing aan basisrelatie
• View ← join van meerdere basisrelaties:
– welke relaties aanpassen?
43
44. voorbeeld
• Wijzig PNAME van John Smith in WORKS_ON1 van 'ProductX'
naar 'ProductY’
UPDATE
WORKS_ON1
SET
Pname
=
'ProductY'
WHERE
Lname
=
'Smith'
AND
Fname
=
'John'
AND
Pname
=
'ProductX’
;
• 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
45. 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')
;
sommige aanpassingen zijn zinloos:
UPDATE
DEPT_INFO
SET
TOTAL_SAL=100000
WHERE
DNAME='Research’
;!
45
46. 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
49. 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
50. referentiële integriteit
• Dno in EMPLOYEE verwijst altijd naar een bestaand
dnumber in DEPARTMENT
foreign key primary key
52. referentiële integriteit
• Dno in EMPLOYEE verwijst altijd naar een bestaand
dnumber in DEPARTMENT
foreign key primary key
6 6
6
53. restricties op attribuut
• NOT NULL (automatisch voor primaire sleutels)
• DEFAULT <value>
• CHECK (voorwaarde)
Dnumber
INT
NOT
NULL
CHECK
(Dnumber
>
0
AND
Dnumber
<
21);
è worden nagekeken bij toevoegen of wijzigen van attribuutwaarden
53
54. algemene restricties specificeren
• andere restricties dan sleutel-, entiteits- en referentiële
restricties opgeven: ASSERTION
• algemene vorm:
CREATE
ASSERTION
<name>
CHECK
<cond>
54
55. voorbeeld
– salaris van werknemer <= salaris van manager van dept.
waarvoor werknemer werkt
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)
)
;!
55
56. 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
57. CHECK-clausule
• kan ook bij
– attribuut - definitie
– CREATE DOMAIN gebruikt worden
• → domeinrestricties
• voorbeeld:
– departementsnummer kan slechts een gehele waarde tussen 1
en 20 zijn:
DNUMBER
INT
NOT
NULL
CHECK
(DNUMBER
>
0
AND
DNUMBER
<
21);
CREATE
DOMAIN
D_NUM
AS
INTEGER
CHECK
(D_NUM
>
0
AND
D_NUM
<
21)
;
57
58. • 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
59. andere mogelijkheden
• CREATE TRIGGER
• hierbij wordt de te nemen actie opgegeven wanneer niet
aan de voorwaarde voldaan is
59
61. 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
62. 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
63. 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