6 - SQL-DML
6 - SQL-DML
Alessandra Raffaetà
raffaeta@[Link]
flessibilità:
- può essere utile vedere i duplicati
- possono servire per le funzioni di aggregazione (es. media)
Il linguaggio comprende
Tutor
Esami
Studenti
Codice: string <<PK>>
Nome: string
Candidato: string <<FK(Studenti)>> <<not null>>
Cognome: string Candidato
Materia: string
Matricola: string <<PK>>
CodDoc: string <<FK(Docenti)>> <<not null>>
Nascita: year
Data: date
Provincia: string
Voto: int
Tutor: string <<FK(Studenti)>>
Lode: bool
CodDoc
Docenti
CodDoc: string <<PK>>
Nome: string
Cognome: string
SELECT *
FROM R1 JOIN R2 ON C2
o
n C2 R2 · · · o
n Cn Rn )
<latexit sha1_base64="0XzTOqb0t4hM9PKHjMFjzOlOUJw=">AAAUM3ic3Vjdktw0Fm7+Fuhll8BcciNoUpVsOT12T88kAzjFMBmW2QokTBj+uru61LLarRpbMpKcmY7j99kX4DW4BYq7rb3dd9gj291jeZwqkgAFuCoVzdH5+b6joyOpZ0nElHbdH5959rnnX/jLiy+93P3rK3/7+6uXXnv9cyVSSegxEZGQX86wohHj9FgzHdEvE0lxPIvoF7OTfTP/xX0qFRP8M71M6CTGIWdzRrAG0fTSB2+PFQtjPM3GMdYLprP9PL9yNPXQ+F+C8Wm2Px3k6Gg6QGMSCK3OxdyI+dW30fRSz+27xYcuDrxq0OtU393pa6//OA4ESWPKNYmwUiPPTfQkw1IzEtG8O04VTTA5wSEdwZDjmKpJVpDN0WWQBGguJPzjGhVSy0LdDyuLs9KkOw7oHPJT/JURKtOIYp5nJF6e5Jnb3x06bt/zHNdxG7q3sDw5okGeyXBmNHe2KyVOT4mIY8yDbIzDkKVc43zkTbKxpme6Ydzz8rxrO/54eZuFC/0VjSJxWrlfZQrA7O7c2BlcH267uzfcrd0BSG4Mt7yt64Pt4a7r7e54FoR/ZONQ0qX6JsWS5nUIdyTmoRHNIkhOpZCjbj1fGY6VWsYzyKypANWcM8K2uVGq5zcmGeNJqikn5cLM0whpgUyloYBJSnS0hAEmksHaIrLAEhMN9WhF0ezkgbXqmUpncxbashifUBac5Tb6JJwnERRmqWs8RWwmsVxmaoETqhyCI/KoyX5IRUy1ZMQJYGVksSlUP4aVYzxs8YmlFKfKUk4gMbGQyQIsnBmgCqVIeaCcRChmVIx8znQrhsB405ICztJ1H+BgmzfBnNCoQVvjWRpheWarzoQ4gRmVI9RInbwvYJFtbS0SghMA1r1cfejgyNLYPFawVpsSz+cYcG0a9NeoHORrC7DpdlcO0N2DI/TPg6O9/Y8OD9D+7b179w67Y2Ok9DKiGYVOtERcBDT3R2b3+mMuZIwjxR7QSaVJdaWXMKJTSTf7hbGfbaaaRWqTnlHiZ2MFkGIWLXOzt+pB7lOyZ1IJIQo30NTIiYPOl8zPVuvrmIGPNVotVRchD50yvUCwrY2TmotJJhLKERQL7KmIol0XQjvdQKTQa6HGlTbr5Hv9YaIdpBZCwrZAN3203d82kq7py8REQT7KKjgUPEBwXZuQ+NQx3RxwBHqx8mc1DMv90LjPJ6058H6jJDwVW4O9qp8PDz85aC2iQgHdOgTZ3tHe14d3PjlE+3c+Pob/bh2ie58d3j7ontcPMIiXZletawckCJVlZbpjUYMogQNnrVGUoymr3EE4YiH3CRxPVAJkY1slMAIfUW2xB3EM04VOcZLRPa2lHdU0wTJZCg50SE1DUMBQ/qCMU/QOON8gXxy2XilMIy1xBaHNZ+ECzVkU+evj7U3PbVRNxaROrpQUJVeM1kko99Z4Nof9zyg0QovkIwg6F9BbyMs4dvyLoCuUMeMsTmO0oIaA75HYWaG7AEol+AETTwHK54LTBrLLjwHt8qOxzcTZ4E9cD0Bv64nobf1R6Hm/s2L/OU1sbdTSyir7U/GzemBE57putoCm+niGWJLG1iwzUzuWbvrl4g63VyQTHMER2GZnUugQJuGd4Ci42lHf7a/N4KnwAD+mseutrA1SFFK4mpEFw7b5Odp27eKyq3VbUIto8/RceQNzpjVuS1RxdXfs4FBnWlN4d+B2m1rMgHJ4HcIlHKsFDdocQNpi2FaEtnkqzZyWBHjvePq8At67dtMxKVlPJbWph9OpPZvUDKfThw3bJLFnm+bcjtuYawa2py9Ebky3hK5pcJuzRZrbpJusuc26SZvbtFt4xzZvm3hsE7/APLaZX6Ae29TbuMvg3EEduVT11ajrnztsUJGqkeZyqmveOPWXtRKwpRT0V0kjc3scDSemNsdECBkwDqLRjEKr93vQMpGYo95gciW5+q7RMeU7Wt+DJwjk5mV6pTeozZeBYbK31YeXiF5cRQ+vFarXHiKQDlfSd1E3b8EGF8Hi7f/LQjP9dVR1sQmCm7lRyPInhd2Cm0AfkvC4wk+O+xfJaAs0c64wuM7xp8jpr55S81vO2LwCbsNDDd+FOzHL3P5gO+9OL/W85k9fFwefD/reTn/46aD3/gfVz2Ivdd7ovNW50vE61zvvdz7q3O0cd0jn353vOt93ftj4duOnjf9s/LdUffaZymajY30b//s/6Aa8SA==</latexit>
… JOIN Rn ON Cn C (R1
WHERE C
SELECT *
FROM Studenti;
SELECT *
FROM Esami
WHERE Voto > 26;
SELECT *
FROM Studenti JOIN Esami ON Matricola = Candidato;
Paolo 71523 VE
Anna 76366 PD
Chiara 71347 VE
SELECT *
FROM Studenti, Esami
Tutte le possibili coppie (Studente, Esame sostenuto dallo studente):
SELECT *
FROM Studenti JOIN Esami ON Matricola = Candidato
Nome dello stuedente e data degli esami per studenti che hanno superato l’esame
di BD con 30:
Se si opera sul prodotto di tabelle con attributi omonimi occorre qualificarli, ovvero
identificare la tabella alla quale ciascun attributo si riferisce
Notazione con il Punto. Utile se si opera su tabelle diverse con attributi aventi lo
stesso nome
[Link]
Es. generare una tabella che riporti Codice, Nome, Cognome dei docenti e Codice
degli esami corrispondenti
Alias
Es. generare una tabella che contenga cognomi e matricole degli studenti e dei
loro tutor
Attributi ::= *
| Expr [[AS] Nome] {, Expr [[AS] Nome] }
usato per rinominare attributi o più comunemente per dare un nome ad un attributo
calcolato
NB:si usano tutte funzioni di aggregazione (-> produce un’unica riga) o nessuna.
è diverso da
SELECT MIN(Nascita), MAX(Nascita), AVG(DISTINCT Nascita)
FROM Studenti
SELECT COUNT(Tutor)
FROM Studenti
CROSS JOIN
realizza il prodotto
SELECT *
FROM Esami CROSS JOIN Docenti
NATURAL JOIN
è il join naturale
SELECT *
FROM Esami NATURAL JOIN Docenti;
Esempio: Esami di tutti gli studenti, con nome e cognome relativo, elencando
anche gli studenti che non hanno fatto esami
Risultato
+---------+---------+-----------+------------+---------+
| Nome | Cognome | Matricola | Data | Materia |
+---------+---------+-----------+------------+---------+
| Chiara | Scuri | 71346 | NULL | NULL |
| Giorgio | Zeri | 71347 | NULL | NULL |
| Paolo | Verdi | 71523 | 2006-07-08 | BD |
| Paolo | Verdi | 71523 | 2006-12-28 | ALG |
| Paolo | Poli | 71576 | 2007-07-19 | ALG |
| Paolo | Poli | 71576 | 2007-07-29 | FIS |
| Anna | Rossi | 76366 | 2007-07-18 | BD |
| Anna | Rossi | 76366 | 2007-07-08 | FIS |
+---------+---------+-----------+------------+---------+
Nota: compaiono anche ennuple corrispondenti a studenti che non hanno fatto
esami, completate con valori nulli.
Inserendo la clausola
ORDER BY Attributo [DESC|ASC] {, Attributo [DESC|ASC] }
si può far sì che la tabella risultante sia ordinata, secondo gli attributi indicati
(ordine lessicografico) in modo crescente (ASC) [default] o decrescente (DESC):
e.g.
SELECT Nome,Cognome
FROM Studenti
WHERE Provincia=’VE’
ORDER BY Cognome DESC, Nome DESC
Es: Nome, cognome e matricola degli studenti di Venezia e di quelli che hanno
preso più di 28 in qualche esame
A differenza dell’algebra relazionale che richiede schemi identici, per gli operatori
insiemistici in SQL si richiede solo che gli attributi siano in pari numero e che
abbiano domini compatibili.
SELECT Matricola
FROM Studenti
EXCEPT
SELECT Tutor
FROM Studenti
Effettuano la rimozione dei duplicati, a meno che non sia esplicitamente richiesto il
contrario con l’opzione ALL
Es: Nome e cognome degli studenti che hanno preso in un esame 18 e in un altro
esame 30
...
p q p∧q p∨q
T T T T
T F F T
p ¬p T U U T
T F F T F T
F T F F F F
U U F U F U
U T U T
U F F U
U U U U
+---------+---------+-----------+---------+-----------+-------+
| Nome | Cognome | Matricola | Nascita | Provincia | Tutor |
+---------+---------+-----------+---------+-----------+-------+
| Anna | Rossi | 76366 | 1987 | PD | NULL |
| Paolo | Verdi | 71523 | 1986 | VE | NULL |
+---------+---------+-----------+---------+-----------+-------+
Cosa ritorna?
SELECT *
FROM Studenti
WHERE Tutor = NULL
COALESCE(Expr1, …, Exprn)
Viene usato per trasformare un valore NULL in un valore non nullo. Valuta le
espressioni in sequenza, da sinistra verso destra. Viene restituito il primo valore
trovato diverso da NULL. L’operatore ritorna NULL se tutte le espressioni hanno
valore NULL.
Su valori numerici
SELECT *
FROM Studenti
WHERE Matricola BETWEEN 71000 AND 72000;
+---------+---------+-----------+---------+-----------+-------+
| Nome | Cognome | Matricola | Nascita | Provincia | Tutor |
+---------+---------+-----------+---------+-----------+-------+
| Chiara | Scuri | 71346 | 1987 | VE | 71523 |
| Giorgio | Zeri | 71347 | 1986 | VE | 76366 |
| Paolo | Verdi | 71523 | 1986 | VE | NULL |
| Paolo | Poli | 71576 | 1985 | PD | 76366 |
+---------+---------+-----------+---------+-----------+-------+
Sulle stringhe
_ un carattere qualsiasi
SELECT *
FROM Studenti
WHERE Nome LIKE 'A_ % '
Studenti con il nome che inizia per ‘A’ e termina per ‘a’ oppure ‘i’
SELECT *
FROM Studenti
WHERE Nome LIKE 'A%a' OR Nome LIKE ‘A%i’
SELECT *
FROM Studenti
WHERE REGEXP_LIKE (Nome,'^A.*(a|i)$’)
Si può
eseguire confronti con l’insieme di valori ritornati dalla sottoselect (sia quando
questo è un singoletto, sia quando contiene più elementi)
Studenti che vivono nella stessa provincia dello studente con matricola 71346,
escluso lo studente stesso
SELECT *
FROM Studenti
WHERE (Matricola <> ’71346’) AND
Provincia = (SELECT Provincia
FROM Studenti
WHERE Matricola=’71346’)
E` indispensabile la sottoselect?
SELECT altri.*
FROM Studenti altri, Studenti s
WHERE [Link] <> '71346' AND
[Link] = '71346' AND [Link] = [Link]
... è un join
SELECT altri.*
FROM Studenti altri JOIN Studenti s USING (Provincia)
WHERE [Link] <> '71346' AND
[Link] = '71346’;
HaSostenuto Candidato
Studenti Esami Studenti Esami
Gli studenti che hanno preso sempre (solo, tutti) 30: universale
Gli studenti che hanno preso qualche (almeno un) 30: esistenziale
Gli studenti che non hanno preso mai 30 (senza alcun 30): universale
Non tutti i voti sono =30 (universale) = esiste un voto ≠30 (esistenziale)
Più formalmente
Più formalmente
SELECT ...
FROM ...
calcola la sottoselect
SELECT *
FROM Studenti s
WHERE EXISTS (SELECT *
FROM Esami e
WHERE [Link] = [Link]
AND [Link] > 27)
La stessa query, ovvero gli studenti con almeno un voto > 27, tramite giunzione:
SELECT DISTINCT s.*
FROM Studenti s JOIN Esami e ON [Link] = [Link]
WHERE [Link] > 27
SELECT ...
FROM ...
calcola la sottoselect
verifica se Expr è in relazione Comp con almeno uno degli elementi ritornati
dalla select
La solita query
“Studenti che hanno preso almeno un voto > 27”
si può esprimere anche tramite ANY ...
SELECT *
FROM Studenti s
WHERE [Link] =ANY (SELECT [Link]
FROM Esami e
WHERE [Link] >27)
SELECT *
FROM Studenti s
WHERE 27 <ANY (SELECT [Link]
FROM Esami e
WHERE [Link] = [Link])
diventa
SELECT *
FROM Tab1
WHERE EXISTS (SELECT *
FROM Tab2
WHERE C AND attr1 op attr2);
FROM ...
SELECT *
FROM Studenti s
WHERE [Link] IN (SELECT [Link]
FROM Esami e
WHERE [Link] >27)
EXISTS
Giunzione
IN
SELECT *
FROM Studenti s
WHERE FORALL e IN Esami WHERE [Link] = [Link]:
[Link] = 30
In SQL non c’e` un operatore generale esplicito FOR ALL. Si usa l’equivalenza
logica
⇤e ⇥ E. P ¬(⌅e ⇥ E. ¬P )
Quindi da:
SELECT *
FROM Studenti s
WHERE FORALL e IN Esami WHERE [Link] = [Link]:
[Link] = 30
In SQL diventa:
Sostituendo EXISTS con =ANY, la solita query (studenti con tutti 30):
SELECT * FROM Studenti s
WHERE NOT EXISTS (SELECT *
FROM Esami e
WHERE [Link] = [Link]
AND [Link] <> 30)
Diventa:
SELECT *
FROM Studenti s
WHERE NOT([Link] =ANY (SELECT [Link]
FROM Esami e
WHERE [Link] <> 30))
...
SELECT *
FROM Studenti s
WHERE NOT([Link] =ANY (SELECT [Link]
FROM Esami e
WHERE [Link] <> 30))
Ovvero:
SELECT * FROM Studenti s
WHERE [Link] <>ALL (SELECT [Link]
FROM Esami e
WHERE [Link] <> 30)
ritorni
+---------+---------+---------+------+
| Nome | Cognome | Materia | Voto |
+---------+---------+---------+------+
| Chiara | Scuri | NULL | NULL |
| Giorgio | Zeri | NULL | NULL |
| Paolo | Verdi | BD | 27 |
| Paolo | Verdi | ALG | 25 |
| Paolo | Poli | ALG | 21 |
| Paolo | Poli | FIS | 22 |
| Anna | Rossi | BD | 30 |
| Anna | Rossi | FIS | 30 |
+---------+---------+---------+------+
Qual e` l’ouput della query ‘studenti che hanno preso solo trenta’?
SELECT [Link]
FROM Studenti s
WHERE NOT EXISTS (SELECT *
FROM Esami e
WHERE [Link] = [Link]
AND [Link] <> 30)
+---------+
| Cognome |
+---------+
| Scuri |
| Zeri |
| Rossi |
+---------+
Se voglio gli studenti che hanno preso solo trenta, e hanno superato qualche
esame:
SELECT *
FROM Studenti s
WHERE NOT EXISTS (SELECT *
FROM Esami e
WHERE [Link] = [Link]
AND [Link] <> 30)
AND EXISTS (SELECT *
FROM Esami e
WHERE [Link] = [Link])
Oppure:
SELECT [Link], [Link]
FROM Studenti s JOIN Esami e ON [Link] = [Link]
GROUP BY [Link], [Link]
HAVING MIN([Link]) = 30;
Per ogni materia, trovare nome della materia e voto medio degli esami in quella
materia [selezionando solo le materie per le quali sono stati sostenuti più di tre
esami]:
Soluzione:
Costrutto:
Semantica:
FROM Esami
GROUP BY Candidato
HAVING AVG(Voto) > 23;
+--------+---------+-----------+------------+------+------+--------+
| Codice | Materia | Candidato | Data | Voto | Lode | CodDoc |
+--------+---------+-----------+------------+------+------+--------+
| B112 | BD | 71523 | 2006-07-08 | 27 | N | AM1 |
| A143 | ALG | 71523 | 2006-12-28 | 25 | N | NG2 |
| B247 | BD | 76366 | 2007-07-18 | 30 | L | AM1 |
| A213 | ALG | 71576 | 2007-07-19 | 21 | N | NG2 |
| F31 | FIS | 76366 | 2007-07-08 | 30 | N | GL1 |
| F45 | FIS | 71576 | 2007-07-29 | 22 | N | GL1 |
+————+---------+-----------+------------+------+------+--------+
+--------+---------+-----------+------------+------+------+--------+
| Codice | Materia | Candidato | Data | Voto | Lode | CodDoc |
+--------+---------+-----------+------------+------+------+--------+
| B112 | BD | 71523 | 2006-07-08 | 27 | N | AM1 |
| A143 | ALG | 71523 | 2006-12-28 | 25 | N | NG2 |
+--------+---------+-----------+------------+------+------+--------+
| A213 | ALG | 71576 | 2007-07-19 | 21 | N | NG2 |
| F45 | FIS | 71576 | 2007-07-29 | 22 | N | GL1 |
+--------+---------+-----------+------------+------+------+--------+
| B247 | BD | 76366 | 2007-07-18 | 30 | L | AM1 |
| F31 | FIS | 76366 | 2007-07-08 | 30 | N | GL1 |
+--------+---------+-----------+------------+------+------+--------+
+-----------+--------+-----------+-----------+-----------+
| Candidato | NEsami | min(Voto) | max(Voto) | avg(Voto) |
+-----------+--------+-----------+-----------+-----------+
| 71523 | 2 | 25 | 27 | 26.000 |
| 76366 | 2 | 30 | 30 | 30.000 |
+-----------+--------+-----------+-----------+-----------+
SELECT DISTINCT X, F τZ
FROM R1,…,Rn
WHERE C1 πX,F
GROUP BY Y
HAVING C2 σC2
ORDER BY Z
YγG
X, Y, Z sono insiemi di attributi
σC1
F, G sono insiemi di espressioni
aggregate, tipo count(*) o sum(A)
×
È necessario scrivere:
Gli attributi aggregati (AVG([Link])) vanno scelti tra quelli non raggruppati
Non va ...
Es: Matricole dei tutor e relativo numero di studenti di cui sono tutor
+-------+-------+
| Tutor | NStud |
+-------+-------+
| NULL | 2 |
| 71347 | 2 |
| 71523 | 1 |
+-------+-------+
Sottoselect:
SELECT [DISTINCT] Attributi
FROM Tabelle
[WHERE Condizione]
[GROUP BY A1,..,An [HAVING Condizione]]
Select:
Sottoselect
{ (UNION [ALL] | INTERSECT [ALL] | EXCEPT [ALL])
Sottoselect }
[ ORDER BY Attributo [DESC] {, Attributo [DESC]} ]
UPDATE Tabella
SET Attributo = Expr, …, Attributo = Expr
WHERE Condizione
m può essere < del numero di attributi n (le restanti colonne o prendono il valore di
default o NULL)
Esempio
Tutti i valori dichiarati NOT NULL e senza un valore di default dichiarato devono
essere specificati
La selezione delle righe da cancellare può essere basata anche su di una select.
Es. Cancella gli studenti che non hanno sostenuto esami
Esempio:
UPDATE Studenti
SET Tutor=’71523’
WHERE Matricola=’76366’ OR Matricola=’76367’