Manuale SQL
Manuale SQL
Capitolo 1
Introduzione alle query
Capitolo 2
Espressioni e operatori condizionali
Capitolo 3
Funzioni
Capitolo 4
Le clausole SQL
Capitolo 5
Join - Combinazione di tabelle
Capitolo 6
Subquery
Capitolo 7
Manipolare i dati
Capitolo 8
Creare e mantenere tabelle
Capitolo 9
VIEW e INDICI
Fondamenti di SQL
Capitolo 1
Introduzione alle query
Prime elementari regole
La sintassi del linguaggio SQL abbastanza flessibile, sebbene ci siano delle
regole da rispettare come in qualsiasi linguaggio di programmazione.
SELECT COGNOME, NOME
FROM PRESIDENTE
WHERE COGNOME = 'Pertini'
In questo esempio tutti i caratteri, a parte 'Pertini', sono scritti in maiuscolo,
ma non deve essere necessariamente cos. Avremmo potuto anche scrivere
cos:
select cognome, nome
from presidente
where cognome = 'Pertini'
si noti per che 'Pertini' scritto sempre nello stesso modo, infatti i riferimenti
ai contenuti di un database devono essere scritti con lo stesso tipo di caratteri
in cui sono stati registrati.
Le parole chiave che abbiamo usato nella query sono:
SELECT
FROM
WHERE
'cognome' e 'nome' sono dei campi e 'presidente' una tabella. Quindi il
comando recita: seleziona visualizzandoli, i campi cognome e nome della
tabella presidente la dove cognome = 'Pertini'.
Esempio:
ASSEGNI
Assegno
Beneficiari
Importo
Note
Computer Shop
500.000
Stampante
954.000
Assicurazioni
ASSO
Assicurazioni
automobili
SNAM
650.000
Riscaldamento casa
Supermarket GS
490.000
Alimentari
Scuola
490.000
Scuola di musica
3
4
5
con l'espressione:
select * from assegni;
si ottiene:
Assegno
Beneficiari
Importo
Note
Computer Shop
500.000
Stampante
Assicurazioni
ASSO
954.000
Assicurazioni
automobili
SNAM
650.000
Riscaldamento casa
Supermarket GS
490.000
Alimentari
Scuola
490.000
Scuola di musica
Assegno
500.000
954.000
650.000
490.000
490.000
Altro esempio:
DOCENTI
Nome
Cognome
Materia
Lara
Bianco
Italiano
Lara
Bianco
Storia
Mario
Guidi
Diritto
Mario
Guidi
Economia
Anna
Rossi
Matematica
Con l'espressione:
SELECT DISTINCT NOME, COGNOME
FROM DOCENTI;
si ottiene:
Nome
Cognome
Bianco
Lara
Guidi
Mario
Rossi
Anna
ESERCIZI (capitolo 1)
1. Le seguenti query non funzionano. Perch?
a. Select * from persone
b. Select *
c. Select nome cognome FROM persone;
2. Le seguenti istruzioni forniscono lo stesso risultato?
COGNOME
ETA
Giovanni
Bruni
62
Antonio
Rossi
43
Mario
Rossi
49
Piero
Bianchi
37
Esmeralda
Gnocca
31
6.
7. Dalla tabella sottostante estrapolare, senza ripetizioni, le squadre di
calcio presenti.
TIFOSERIA
NOME
COGNOME
SQUADRA_APPARTENENZA
ARTURO
ROSSI
LAZIO
GIOVANNI ROSSI
LAZIO
MARIO
ROSSI
LAZIO
MARIA
MARCHETTI NAPOLI
MARIA
MARCHETTI ROMA
9.
10.La seguente query giusta? e se sbagliata, perch?
SELECT NOME, DISTINCT SQUADRA_APPARTENENZA
FROM TIFOSERIA;
11.La seguente query giusta? e se sbagliata, perch?
SELECT DISTINCT COGNOME, NOME
FROM TIFOSERIA;
12.La seguente query giusta? e se sbagliata, perch?
SELECT DISTINCT *
FROM TIFOSERIA;
SOLUZIONI ESERCIZI CAPITOLO 1
1)
a. Non funziona perch manca il carattere di fine istruzione.
b. incompleta; manca la clausola FROM seguita dal nome di una tabella.
c. Manca la virgola tra nome e cognome.
2) Si.
3) Sono tutte corrette.
4)
SELECT ETA, NOME
FROM ANAGRAFICA;
5)
SELECT DISTINCT SQUADRA_APPARTENENZA
FROM TIFOSERIA;
Capitolo 2
Espressioni e operatori condizionali
Condizioni
Tutte le volte che si vuole trovare un particolare elemento o gruppo di
elementi in un database, occorre specificare una o pi condizioni. Le
condizioni sono introdotte dalla clausola WHERE.
Esempio:
STUDENTI
NOME
Cognome
ANNO
Classe
Sezione
Mario
Bianchi
1976
Anna
Bianco
1973
Marta
Carli
1974
Gianni
Rossi
1972
Giulio
Mancini
1972
Max
Zunini
1976
con l'espressione:
SELECT *
FROM STUDENTI
WHERE CLASSE = 5
AND SEZIONE = 'A';
si ottiene:
NOME
Cognome
ANNO
Classe
Sezione
Giulio
Mancini
1972
Operatori aritmetici
Sono gli operatori aritmetici: + (somma), - (sottrazione), / (divisione), *
(moltiplicazione).
L'operatore somma:
data la tabella
PREZZO
Elemento
PrezzoIngrosso
Pomodori
340
Patate
510
Banane
670
Rape
450
Arance
890
Mele
230
PREZZOINGROSSO
PREZZOINGROSSO
+ 150
Pomodori
340
490
Patate
510
660
Banane
670
820
Rape
450
600
Arance
890
1040
Mele
230
380
Operatore sottrazione:
l'operatore meno svolge due funzioni. La prima quella di cambiare il segno
a un numero, la seconda quella di sottrarre i valori di una colonna da quelli
di un'altra colonna. Vediamo il primo caso:
MINMAX
Regione
TempMin
TempMax
Piemonte
-4
10
Toscana
13
Sicilia
10
19
Lombardia
-2
Friuli
-3
con l'espressione
SELECT REGIONE, -TEMPMIN, -TEMPMAX
FROM MINMAX;
si ottiene
REGIONE
TEMPMIN
TEMPMAX
Piemonte
-10
Toscana
-4
-13
-10
-19
Lombardia
-9
Friuli
-8
Sicilia
DIFFERENZA
Piemonte
14
9
Toscana
9
Sicilia
11
Lombardia
11
Friuli
PrezzoIngrosso
Pomodori
340
Patate
510
Banane
670
Rape
450
Arance
890
Mele
230
con l'espressione
SELECT Elemento, PrezzoIngrosso, (PrezzoIngrosso / 2) PrezzoVendita
FROM PREZZO;
si ottiene
ELEMENTO PREZZOINGROSSO PREZZOVENDITA
Pomodori
340
170
Patate
510
255
Banane
670
335
Rape
450
225
Arance
890
445
Mele
230
115
PrezzoIngrosso
Pomodori
340
Patate
510
Banane
670
Rape
450
Arance
890
Mele
230
con l'espressione
SELECT Elemento, PrezzoIngrosso, (PrezzoIngrosso * 0.9) NuovoPrezzo
FROM PREZZO;
si ottiene
ELEMENTO PREZZOINGROSSO NUOVOPREZZO
Pomodori
340
306
Patate
510
459
Banane
670
603
Rape
450
405
Arance
890
801
Mele
230
207
Operatori di confronto
L'operatore (=):
Esempio: dalla seguente tabella vogliamo estrapolare tutti i dati dell'amico
Mario
AMICI
Nome
Cognome
Telefono
Giovanni
Bruni
0763 546432
Antonio
Rossi
06 756499
Mario
Rossi
02 435591
Piero
Bianchi
06 326799
SELECT *
FROM AMICI
WHERE NOME = 'Mario';
NOME
COGNOME
TELEFONO
Mario
Rossi
02 435591
Gli operatori: maggiore (>) , maggiore o uguale (>=), minore (<), minore
o uguale (<=), diverso (<>):
Questi operatori si usano allo stesso modo di come si usa l'operatore di
uguaglianza. Vediamo alcuni esempi:
ANAGRAFICA
Nome
Cognome
Et
Giovanni
Bruni
55
Antonio
Rossi
43
Mario
Rossi
49
Piero
Bianchi
37
NOME
COGNOME
ET
Giovanni
Bruni
55
Mario
Rossi
49
SELECT *
FROM ANAGRAFICA
WHERE Et <> 55;
NOME
COGNOME
ET
Antonio
Rossi
43
Mario
Rossi
49
Piero
Bianchi
37
L'operatore IS:
Modifichiamo ora la tabella ANAGRAFICA inserendo un altro nominativo di
cui per non sappiamo l'et. In questo caso nel campo ETA verr inserito in
maniera 'automatica' il valore NULL che identifica l'assenza di dati:
NOME
COGNOME
ETA
Giovanni
Bruni
55
Antonio
Rossi
43
Mario
Rossi
49
Piero
Bianchi
37
Esmeralda
Gnocca
COGNOME
Esmeralda
Gnocca
ETA
Operatori di caratteri
Gli operatori di caratteri possono essere utilizzati per manipolare il modo in
cui le stringhe devo essere ricercate.
Operatore LIKE:
possibile estrarre da un database quei dati che assomigliano a un certo
schema, senza essere perfettamente identici allo schema specificato.
Vediamo qualche esempio:
Nome
ANATOMIA
Posizione
Fegato
Destra-Addome
Cuore
Petto
Faringe
Gola
Vertebre
Centro-Dorso
Incudine
Orecchio
Rene
Dorso
SELECT *
FROM ANATOMIA
WHERE Posizione LIKE '%Dorso%';
Nome
Posizione
Vertebre
Centro-Dorso
Rene
Dorso
Si noti l'uso del segno '%' dopo LIKE. Esso rappresenta zero, uno o pi
caratteri. Il corrispondente carattere implementato da Access '*'.
Nome
Posizione
Rene
Dorso
SELECT *
FROM ANATOMIA
WHERE Nome LIKE 'F%';
Nome
Posizione
Destra-Addome
Fegato
Gola
Faringe
Cognome
Provincia
Giovanni
Bruni
CO
Antonio
Rossi
MI
Mario
Rossi
CT
Piero
Bianchi
PV
Nome
Cognome
Provincia
Giovanni
Bruni
CO
Mario
Rossi
CT
SELECT *
FROM NOMINATIVI
WHERE Provincia LIKE 'C_';
NOME
TELEFONO
PR
CAP
ROSSI
ALESSANDRA
0761 556632
BG
01023
VERDI
ALESSANDRA
02 345622
MI
03456
MERRILI
TITTI
0732 433388
CO
01255
BANFI
BARBY
0722 114381
BR
03367
MARIA
0581 931522
CA
09941
JO
0359 118267
PV
01944
CHIARA
0445 668193
CT
01042
PERSIANI
MAZZA
BORDONI
Access non implementa, oltre che l'operatore '||', anche questo modo di
ridenominare le colonne estrapolate:
SELECT NOME || COGNOME NOMECOMPLETO
Ecco un'altra applicazione dell'operatore di concatenazione:
SELECT COGNOME || ', ' || NOME AMICO
FROM AMICI;
AMICO
ROSI, ALESSANDRA
VERDI, ALESSANDRA
MERRILI, TITTI
BANFI, BARBY
PERSIANI, MARIA
MAZZA, JO
BORDONI, CHIARA
r = a AND b
FALSO
FALSO
VERO
FALSO
FALSO
FALSO
VERO
VERO
FALSO
FALSO
VERO
VERO
Disgiunzione logica:
Date le proposizioni:
a: il quadrato un poligono
b: Dante un poeta
la proposizione:
r : il quadro un poligono o Dante un poeta
una proposizione composta, ottenuta operando sulle proposizioni a e b per
mezzo del connettivo o. L'operazione binaria che da come risultato il valore di
verit r si chiama disgiunzione logica.
DEFINIZIONE: Si chiama disgiunzione logica un'operazione che ad ogni
coppia di proposizioni a, b associa la proposizione composta r che vera se
almeno una delle due proposizioni vera, falsa se a e b sono entrambe false.
Il connettivo disgiunzione logica viene indicato con OR. La tavola della verit
della disgiunzione logica la seguente e si ottiene considerando tutte le
possibile coppie di valori di verit attribuibili ad a e b.
a
R = a OR b
FALSO
FALSO
FALSO
FALSO
VERO
VERO
VERO
FALSO
VERO
VERO
VERO
VERO
Negazione logica:
Date le proposizioni:
a: 3 un numero dispari
b: 3 non un numero dispari
evidente che la proposizione b la negazione della proposizione a.
Possiamo dire che b si ottiene da a mediante la sua negazione.
DEFINIZIONE: Si chiama negazione logica un'operazione che ad una
proposizione a, associa la proposizione b la quale risulta vera se a falsa e
falsa se a vera.
La negazione logica viene indicata con NOT. La tavola della verit della
negazione logica la seguente.
a
NOT a
FALSO
VERO
VERO
FALSO
Negli esempi che utilizzeremo, per meglio comprendere gli operatori logici,
non appariranno espressioni booleane complesse ma espressioni semplici,
cio composte da un solo operatore. Dobbiamo far presente per, che tali
operatori sono utilizzabili come qualsiasi altro operatore matematico, dunque
nulla ci impedisce di creare delle vere e proprie espressioni algebriche lunghe
a piacere.
La breve panoramica sull'algebra booleana termina qui; vista la semplicit
dell'argomento lasciamo al lettore il compito di utilizzare e 'trasferire' quanto a
appreso, alle specifiche del linguaggio SQL.
Operatore AND:
Indica che entrambe le espressioni che si trovano ai suoi lati devono essere
soddisfatte, vediamo un esempio:
FERIE
COGNOME
ID_DIPENDENTE
ANNI
FERIE_GODUTE
MARINI
101
ROSSI
104
23
ZAPPA
107
45
VERDI
233
80
BOLDI
210
15
100
GIALLI
211
10
78
L'operatore OR:
sufficiente che una sola espressione sia verificata per ottenere il valore
TRUE, vediamo un esempio:
vogliamo sapere i cognomi dei dipendenti che non hanno pi di 5 anni di
servizio o hanno goduto ferie per pi di 80 giorni.
SELECT COGNOME
FROM FERIE
WHERE ANNI <= 5
OR FERIE_GODUTE > 80;
COGNOME
MARINI
ROSSI
ZAPPA
VERDI
BOLDI
Operatore NOT:
Ha il compito di invertire il significato di una condizione, vediamo un esempio:
vogliamo conoscere i cognomi che non iniziano per B.
SELECT COGNOME
FROM FERIE
WHERE COGNOME NOT LIKE 'B%';
COGNOME
MARINI
ROSSI
ZAPPA
VERDI
GIALLI
A = {9, B}
Intersezione:
Si definisce intersezione fra A e B il sottoinsieme formato dagli elementi
comuni agli insiemi A e B.
L'intersezione fra gli insiemi A e B si indica scrivendo:
A = {G, 9, R}
B = {9, B}
B = {9, B}
A \ B = {G, R}
CALCETTO
NOME
NOME
MARINI
MARINI
BRAVO
BACCO
ROSSI
ROSSI
VERDI
DINI
MARRONI
MARRONI
GIALLI
FALCONE
GIANNINI
GIANNINI
DINI
MARRONI
FALCONE
GIALLI
GIANNINI
Operatore INTERSECT:
NOME
TELEFONO
PR
CAP
ROSSI
MARIA
0761 556632
BG
01023
VERDI
MARIA
02 345622
MI
03456
MARRONI
ANTONIO
0732 433388
CO
01255
BANFI
BARBY
0722 114381
BR
03367
PERSIANI
LUCA
0581 931522
CA
09941
MAZZA
ALBERTO
0359 118267
PV
01944
BATTISTI
CHIARA
0445 668193
CT
01042
SELECT *
FROM AMICI
WHERE PR IN ('CO', 'PV', 'BG');
NOME
TELEFONO
PR
CAP
ROSSI
MARIA
23423
BG
01023
MARRONI
ANTONIO
45567
CO
01255
MAZZA
ALBERTO
567878
PV
01944
PREZZO_INGROSSO
POMODORI
340
PATATE
510
BANANE
670
RAPE
450
ARANCE
890
230
MELE
SELECT *
FROM PREZZO
WHERE PREZZO_INGROSSO
>= 250
AND
PREZZO_INGROSSO <= 750;
SELECT *
FROM PREZZO
WHERE PREZZO_INGROSSO
BETWEEN 250
AND 750;
PREZZO_INGROSSO
POMODORI
340
PATATE
510
BANANE
670
RAPE
450
ESERCIZI (capitolo 2)
Utilizzare la tabella AMICI, qui riportata, per rispondere ai quesiti dove non
specificata altra tabella.
AMICI
COGNOME
NOME
PR
ROSSI
MARIA
BG
VERDI
MARIA
MI
MARRONI
ANTONIO
CO
BANFI
BARBY
BR
PERSIANI
LUCA
CA
MAZZA
ALBERTO
PV
BATTISTI
CHIARA
CT
1) Scrivere una query per selezionare tutti i cognomi che iniziano con la
lettera M.
2) Scrivere una query per selezionare gli amici che vivono in provincia di
Bergamo (BG) e il cui nome MARIA.
3) Quale il risultato di questa query?
SELECT NOME, COGNOME
FROM AMICI
WHERE NOME = 'MARIA'
OR COGNOME = 'MAZZA';
4) Quale il risultato di questa query?
SELECT NOME, COGNOME
FROM AMICI
WHERE NOME = 'MARIA'
AND COGNOME = 'MAZZA';
5) Quale scorciatoia potrebbe essere utilizzata in alternativa a WHERE A >=
10 AND A <= 30 ?
6) Scrivere una interrogazione che dalla tabella sottostante estrapoli il nome
delle donne sposate
PERSONE
ID_PERSONA
NOME
ID_CONIUGE
SESSO
ANTONIO
12
12
SILVIA
GIULIO
MARIA
ROBERTA
ANTONELLA
ARTURO
PrezzoIngrosso
Pomodori
340
Patate
510
Banane
670
Rape
450
Arance
890
Mele
230
10) Scrivere un interrogazione che inverta il segno dei valori presenti nella
colonna PrezzoIngrosso della
tabella PREZZI.
Il database costituito dalle tabelle Cacciatori, Pescatori e Scalatori appartiene
ad un circolo sportivo e contiene i nominativi degli iscritti a tale circolo. Gli
iscritti sono raggruppati sulle tabelle in base allo sport che essi fanno.
Chiaramente la stessa persona pu fare pi di uno sport e quindi comparire
in pi di una tabella. Per gli esercizi seguenti faremo riferimento a questo
piccolo database.
CACCIATORI
PESCATORI
SCALATORI
Codice
Nome
Codice
Nome
Codice
Nome
35
ROSSI
ROSSI
27
NERI
27
NERI
77
MANCINI
11
MARCA
12
BINACHI
49
CRUCIANI
MICHELI
BISCARDI
11
MARCA
BISCARDI
11) Scrivere una query per visualizzare tutti i nominativi iscritti al circolo.
12) Scrivere una query per visualizzare i cacciatori che non siano anche
scalatori.
13) Scrivere una query per visualizzare gli scalatori che non siano anche
cacciatori.
14) Scrivere una query per visualizzare i pescatori che siano anche
cacciatori.
15) Se dovessimo scrivere una query per visualizzare i cacciatori che siano
anche pescatori potremmo
utilizzare la soluzione dell'esercizio N 14?
16) Scrivere una query per visualizzare tutti i nominativi iscritti al circolo il cui
nome finisce con 'I' e ci sia
almeno una 'A'.
17) Scrivere una query per visualizzare tutti i nominativi iscritti al circolo il cui
nome finisce con 'I' o ci sia
almeno una 'A'.
SOLUZIONI ESERCIZI CAPITOLO 2
1)
SELECT COGNOME
FROM AMICI
WHERE COGNOME LIKE 'M%' ;
Alcuni DBMS, come Access, implementano '*' invece '%'
2)
SELECT COGNOME, NOME
FROM AMICI
WHERE NOME = 'MARIA'
AND PR = 'BG';
3)
NOME
COGNOME
MARIA
ROSSI
MARIA
VERDI
ALBERTO
MAZZA
5)
BETWEEN 10 AND 30
6)
SELECT NOME
FROM PERSONE
WHERE CONIUGE IS NOT NULL
AND SESSO = 'F';
7)
SELECT NOME
FROM PERSONE
WHERE NOME LIKE 'A%O';
Bisogna ricordare che il corrispondente carattere '%' implementato da Access
'*'.
8)
SELECT NOME
FROM PERSONE
WHERE NOME LIKE '_ _ _O %';
Bisogna ricordare che il corrispondente carattere '_' implementato da Access
'?'.
9)
SELECT *, (PrezzoIngrosso * 1.5) PrezzoVendita
FROM PREZZI;
Bisogna ricordare che l'assegnazione del nome alla colonna che conterr i
nuovi prezzi, non possibile utilizzando Access 8.0.
10) Le espressioni che possiamo utilizzare sono ameno due:
SELECT - PrezzoIngrosso
FROM PREZZI;
11)
SELECT *
FROM CACCIATORI
UNION
SELECT *
FROM PESCATORI
UNION
SELECT *
FROM SCALATORI;
12)
SELECT *
FROM CACCIATORI
MINUS
SELECT *
FROM SCALATORI;
Bisogna ricordare che l'operatore MINUS non implementato da Access 8.0
13)
SELECT *
FROM SCALATORI
MINUS
SELECT *
FROM CACCIATORI;
14)
SELECT *
FROM PESCATORI
INTERSECT
SELECT *
FROM CACCIATORI;
Bisogna ricordare che l'operatore INTERSECT non implementato da
Access 8.0
15) Si.
16)
SELECT *
FROM CACCIATORI
WHERE NOME LIKE ' %A%I'
UNION
SELECT *
FROM PESCATORI
WHERE NOME LIKE ' %A%I'
UNION
SELECT *
FROM SCALATORI
WHERE NOME LIKE ' %A%I';
Bisogna ricordare che il corrispondente carattere ' %' implementato da
Access '*'.
17)
SELECT *
FROM CACCIATORI
WHERE NOME LIKE ' %A %' OR NOME LIKE ' %I'
UNION
SELECT *
FROM PESCATORI
WHERE NOME LIKE ' %A%' OR NOME LIKE ' %I'
UNION
SELECT *
FROM SCALATORI
WHERE NOME LIKE ' %A%' OR NOME LIKE ' %I';
Capitolo 3
Funzioni
Le funzioni, nell'ambito dei linguaggi di terza generazioni (linguaggi
procedurali), sono delle particolari procedure le quali passandogli dei valori
(parametri) esse ci restituiscono (ritornano) un valore.
Anche se SQL non un linguaggio procedurale, implementa le funzioni nella
stessa maniera
ma con una differenza sostanziale:
nei linguaggi procedurali noi stessi possiamo crearci delle funzioni, con SQL
ci non possibile e quindi possiamo utilizzare solo quelle funzioni che ci
mette a disposizione il DBMS che stiamo usando.
In questo capitolo vedremo molte funzioni, ma soltanto le prime 5 (COUNT,
SUM, AVG, MAX e MIN) sono definite nello standard SQL. Queste prime
cinque funzioni sono le pi importanti e dobbiamo impararle bene, esse sono
sempre presenti nella maggior parte dei DBMS a differenza delle restanti, che
a volte non appaiono affatto o sono implementate con una sintassi diversa.
Funzioni aggregate
Le funzioni che analizzeremo in questo paragrafo hanno la particolarit di
restituire un solo valore. Inoltre, dato che operano su insiemi di righe,
vengono anche chiamate funzioni di gruppo.
Gli esempi di questo paragrafo utilizzano la tabella IMPIEGATO:
NOME
COGNOME
IMPIEGATO
DIPARTIMENTO
UFFICIO
STIPENDIO
MARIO
ROSSI
AMMINISTRAZIONE
10
L. 4.500.000
CARLO
BIANCHI
PRODUZIONE
20
L. 360.000
GIUSEPPE
VERDI
AMMINISTRAZIONE
20
L. 4.000.000
FRANCO
NERI
DISTRIBUZIONE
16
L. 4.500.000
CARLO
ROSSI
DIREZIONE
14
L. 7.300.000
LORENZO
LANZI
DIREZIONE
L. 730.000
PAOLA
BORRONI
AMMINISTRAZIONE
75
L. 4.000.000
MARCO
FRANCO
PRODUZIONE
46
L. 4.000.000
COUNT
Restituisce il numero di righe che soddisfano la condizione specificata nella
clausola WHERE.
Vediamo un esempio: voglio conoscere il numero di impiegati che
appartengono al dipartimento produzione
SELECT COUNT (*)
FROM IMPIEGATO
WHERE DIPARTIMENTO = 'PRODUZIONE';
SUM
Questa funzione somma tutti i valori di una colonna, vediamo un esempio:
voglio ottenere la somma di tutti gli stipendi
SELECT SUM(STIPENDIO)
FROM IMPIEGATO;
L.29.390.0000
L. 3.673.750
L. 7.300.000
L. 360.000
La funzione MIN opera anche con i caratteri: la stringa 'AAA' minore della
stringa 'BB'.
STDDEV
Deviazione standard
Questa funzione calcola la deviazione standard di una colonna di numeri.
Non esiste in Access . Vediamo un esempio:
TEMPERATURE
CITTA
TEMPERATURA
---------------------------- ------------------------------------------ROMA
10
ANCONA
NAPOLI
15
SELECT STDDEV(TEMPERATURA)
FROM TEMPERATURE;
STDDEV(TEMPERATURA)
------------------------------------3,6055513
VARIANCE
Quadrato della deviazione standard
Questa funzione calcola il quadrato della deviazione standard. Non esiste in
Access. Vediamo un esempio usando la tabella usata precedentemente:
SELECT VARIANCE(TEMPERATURA)
FROM TEMPERATURE;
VARIANCE(TEMPERATURA)
------------------------------------13
Funzioni temporali
Queste funzioni operano su date e orari; sono molto potenti e quando
servono si rivelano essere molto utili.
Alcuni DBMS, come Access, non le implementano o usano sintassi diverse.
ADD_MONTHS
Questa funzione aggiunge un numero di mesi a una data specificata.
Vediamo un esempio usando la tabella sottostante.
PROGETTO
COMPITO
DATA_INIZIO
DATA_FINE
--------------------------------- ------------------------------- ------------------------------------------AVVIO PROGETTO
01-Apr-99
02-Apr-99
DEFINIZIONE
SPECIFICHE
02-Apr-99
01-Mag-99
CONTROLLO TECNICO
01-Giu-99
30-Giu-99
PROGETTAZIONE
01-Lug-99
02-Set-99
COLLAUDO
03-Set-99
17-Dic-99
DATA_INIZIO
ADD_MONTH
----------------------------------- --------------------------
AVVIO PROGETTO
01-Apr-99
02-Giu-99
DEFINIZIONE
SPECIFICHE
02-Apr-99
01-Lug-99
CONTROLLO TECNICO
01-Giu-99
31-Ago-99
PROGETTAZIONE
01-Lug-99
02-Nov-99
COLLAUDO
03-Set-99
17-Feb-00
LAST_DAY
30-Apr-99
01-Mag-99
31-Mag-99
30-Giu-99
30-Giu-99
02-Set-99
30-Set-99
17-Dic-99
31-Dic-99
MONTHS_BETWEEN
Questa funzione serve per sapere quanti mesi sono compresi tra il mese x e
il mese y.
SELECT COMPITO, DATA_INIZIO, DATA_FINE,
MONTHS_BETWEEN(DATA_FINE, DATA_INIZIO) DURATA
FROM PROGETTO;
COMPITO
DATA_INIZIO
DATA_FINE
DURATA
-------------------------------- ----------------------------- -------------------------- ---------------------------------AVVIO PROGETTO
01-Apr-99
02-Apr-99
,03225806
DEFINIZIONE
SPECIFICHE
02-Apr-99
01-Mag-99
,96774194
CONTROLLO
TECNICO
01-Giu-99
30-Giu-99
,93548387
PROGETTAZIONE
01-Lug-99
02-Set-99
2,0322581
COLLAUDO
03-Set-99
17-Dic-99
3,4516129
NEW_TIME
Questa funzione consente di regolare l'ora e la data in funzione del fuso
orario. Vediamo un esempio utilizzando la tabella Progetto:
NEW_TIME(DATA,
'AST', 'PDT')
02-Apr-99
01-Apr-99
01-Mag-99
30-Apr-99
30-Giu-99
29-Giu-99
02-Set-99
01-Set-99
17-Dic-99
16-Dic-99
SIGLA
AST o ADT
BST o BDT
CST o CDT
EST o EDT
GMT
HST o HDT
MST o MDT
NST
PST o PDT
YST o YDT
NEXT_DAY
Questa funzione imposta una nuova data, successiva a quella passatagli
come primo parametro, in base al giorno della settimana passatogli come
secondo parametro.
SELECT DATA_INIZIO,
NEXT_DAY(DATA_INIZIO, 'VENERDI')
FROM PROGETTO;
DATA_INIZIO
-----------------------------
NEXT_DAY
----------------------
01-Apr-99
02-Apr-99
09-Apr-99
02-Apr-99
04-Giu-99
01-Giu-99
02-Lug-99
01-Lug-99
10-Set-99
03-Set-99
SYSDATE
Questa funzione fornisce la data e l'ora del sistema. Vediamo degli esempi:
SELECT DISTINCT SYSDATE
FROM PROGETTO;
SYSDATE
-------------18-Mar-99
B
----------------------------------4
,707
9
42
55
5,3
ABS
Questa funzione calcola il valore assoluto del numero specificato. Vediamo
un esempio:
SELECT ABS(A)VALORE_ASSOLUTO
FROM NUMERI;
VALORE_ASSOLUTO
----------------------------3,1415
45
5
57,667
15
7,2
CEIL
Questa funzione fornisce il pi piccolo numero intero che maggiore o
uguale al suo argomento.
Questa sintassi non implementata da Access.
SELECT A, CEIL(A) MAX_INTERI
FROM NUMERI;
A
---------------------------3,1415
-45
5
-57,667
15
-7,2
MAX_INTERI
-----------------4
-45
5
-57
15
-7
FLOOR
Questa funzione fornisce il pi grande numero intero che minore o uguale
al suo argomento.
Questa sintassi non implementata da Access.
SELECT A, FLOOR(A) MINIMI_INTERI
FROM NUMERI;
A
---------------------------3,1415
-45
5
-57,667
15
-7,2
MINIMI_INTERI
-----------------3
-45
5
-58
15
-8
SIGN
La funzione SIGN restituisce -1 se il suo argomento minore di zero e
restituisce 1 se il suo argomento maggiore o uguale a zero. Questa
sintassi non implementata da Access. Vediamo un esempio:
SELECT A, SIGN(A)
FROM NUMERI;
SIGN(A)
------------------
A
---------------------------3,1415
-45
5
-57,667
15
-7,2
1
-1
1
-1
1
-1
Funzioni trigonometriche
Le funzioni trigonometriche COS, SIN, TAN sono molto utili in applicazioni in
cui si richiede l'uso di tali calcoli. Tutte queste funzioni operano supponendo
che l'angolo n sia espresso in radianti. Queste funzioni, stranamente, sono
implementate da Access. Vediamo alcuni esempi usando la tabella ANGOLI:
ANGOLI
RADIANTI
--------------3,14
6,28
1,57
COS
Calcola il coseno del parametro passatogli come angolo espresso in radianti:
SELECT RADIANTI, COS(RADIANTI)
FROM ANGOLI;
RADIANTI
COS(RADIANTI)
----------------- ---------------------------------------3,14
-,9999987
6,28
,99999493
1,57
,00079633
SIN
Calcola il seno del parametro passatogli come angolo espresso in radianti:
SELECT RADIANTI, SIN(RADIANTI)
FROM ANGOLI;
RADIANTI
SIN(RADIANTI)
----------------- ---------------------------------------3,14
,00159265
6,28
-,0031853
1,57
,99999968
TAN
Calcola la tangente del parametro passatogli come angolo espresso in
radianti:
SELECT RADIANTI, TAN(RADIANTI)
FROM ANGOLI;
RADIANTI
TAN(RADIANTI)
----------------- ---------------------------------------3,14
-,0015927
6,28
-,0031853
1255,7656
1,57
B
----------------------------------4
,707
9
42
55
5,3
EXP
Questa funzione permette di elevare e a un esponente (e una costante
matematica che viene utilizzata in varie formule). Vediamo un esempio:
SELECT A, EXP(A)
FROM NUMERI;
A
----------------------------3,1415
-45
5
-57,667
15
-7,2
EXP(A)
----------------------------------23,138549
2,863E-20
148,41316
9,027E-26
3269017,4
,00074659
LN
Questa funzione calcola il logaritmo naturale. Questa funzione non
implementata da Access .
Vediamo un esempio in cui si vuole calcolare i logaritmi della colonna A della
tabella NUMERI:
SELECT A, LN(A)
FROM NUMERI;
ERRORE:
ORA-01428: l'argomento '-45' esterno all'intervallo
Il messaggio d'errore che viene visualizzato dato dal fatto che non
possibile determinare un logaritmo di un valore negativo quando la base
positiva: non esiste nessun esponente che elevato ad e (valore positivo) ci da
come risultato un valore negativo.
Il 'problema' pu essere risolto inserendo all'interno della funzione LN la
funzione ABS che ci restituisce i valori assoluti di quelli specificati:
SELECT A, LN(ABS(A))
FROM NUMERI;
A
LN(ABS(A))
------------------------ ---------------------3,1415
1,1447004
-45
3,8066625
5
1,6094379
-57,667
4,0546851
15
2,7080502
-7,2
1,974081
LOG
Questa funzione richiede due argomenti e calcola il logaritmo del secondo
avendo come base il primo. Vediamo un esempio in cui si calcolano i
logaritmi del numero 2 aventi come base i valori della colonna B della tabella
NUMERI:
SELECT B, LOG(B, 2)
FROM NUMERI;
B
LOG(B,2)
--------------------------------------------------------------------------4
,5
,707
-1,999129
9
,31546488
42
,18544902
55
,17296969
5,3
,41562892
A
-----------------------3,1415
-45
5
-57,667
15
-7,2
4
,707
9
42
55
5,3
77,870231
5972090,5
59049
2,467E-94
1,275E+26
6,098E-06
SQRT
Questa funzione implementata da Access con la sintassi
'SQR(nome_campo)'. La funzione SQRT restituisce la radice quadrata di un
argomento. Poich la radice quadrata di un numero negativo non esiste, non
possibile utilizzare questa funzione con i numeri negativi.
Vediamo una esempio:
SELECT B, SQRT(B)
FROM NUMERI;
B
SQRT(B)
,707
9
,84083292
3
42
6,4807407
7,4161985
55
2,3021729
5,3
Funzioni di caratteri
Queste funzioni ci permettono di manipolare i dati da visualizzare in tutti i
modi e formati desiderati. Sono particolarmente utili quando abbiamo la
necessit di rendere i dati pi leggibili o quando vogliamo estrapolare delle
informazioni sulle stringhe e i caratteri rappresentanti le informazioni.
Gli esempi presentati si basano sulla tabella CARATTERI sottostante:
CARATTERI
COGNOME
NOME
CODICE
ROSSI
GIGI
32
BIANCHI
MARIO
67
NERI
MARIA
65
BRUNI
ANGELO
87
SCURI
ANNA
77
VERDI
ANTONIO
52
CHR
Questa funzione fornisce il carattere corrispondente al codice ASCII
passatogli. Vediamo un esempio:
SELECT CODICE, CHR(CODICE)
FROM CARATTERI;
CODICE
CH
---------------------- -----------32
67
65
87
77
52
ESERCIZI
1) Le funzioni di gruppo sono anche chiamate in un altro modo, quale?
2) La seguente query giusta? e se sbagliata, perch?
SELECT SUM(NOME)
FROM PERSONE;
3) Esiste una funzione che trasforma in maiuscolo il primo carattere di una
stringa e in minuscolo tutti gli altri, quale questa funzione?
4) La seguente query sbagliata? e se giusta, perch?
SELECT COUNT(NOME)
FROM PERSONE;
5) Applicando la seguente query alla tabella sottostante
SELECT COUNT(NOME)
FROM PERSONE;
PERSONE
ID_PERSONA
NOME
ANTONIO
12
SILVIA
GIULIO
3
6
ROBERTA
ROBERTA
MARIA
SELECT COUNT(*)
FROM PERSONE;
PERSONE
ID_PERSONA
NOME
ANTONIO
12
SILVIA
GIULIO
3
6
ROBERTA
ROBERTA
MARIA
ID_PERSONA
NOME
ANTONIO
1
SILVIA
12
GIULIO
2
3
ROBERTA
ROBERTA
MARIA
GIGI
32
BIANCHI
MARIO
67
NERI
MARIA
65
BRUNI
ANGELO
87
SCURI
ANNA
77
VERDI
ANTONIO
52
32
1) Funzioni aggregate.
2) La query sbagliata perch non possibile applicare la funzione SUM( )
su una colonna che contiene dati di tipo caratteri o stringa.
3) INITCAP. necessario ricordare per, che questa funzione non
implementata da Access 8.0
4) giusta in quanto conta il numero di nomi selezionati.
5) c
6) a
7) La funzione in grado di farlo CONCAT e l'operatore '||'. necessario
ricordare per, che sia la
funzione CONCAT che l'operatore '||' non sono implementati da Access 8.0.
8) sbagliata, infatti mancano le parentesi che devono racchiudere i
parametri passati alla funzione.
9) sbagliata.
10) La risposta giusta d. necessario per, far notare che questa sintassi
non viene accettata da Access 8.0
11)
SELECT SUBSTR(NOME, 1, 1) ||'.'||
SUBSTR(COGNOME, 1, 1) ||'.' INIZIALI, CODICE
FROM CARATTERI
WHERE CODICE = 32;
necessario ricordare che questa funzione non esiste in Access 8.0.
Capitolo 4
Le clausole SQL
Questo capitolo dedicato alle clausole utilizzate con l'istruzione SELECT ,
in particolare saranno trattate le seguenti clausole:
WHERE
ORDER BY
GROUP BY
HAVING
COMPUTER SHOP
LIBRERIE CULTURA
COMPUTER SHOP
200 000
BIOGAS SRL
SUPERMARCHET GS
16
ASSICURAZIONI ASSO
17
GAS S.P.A.
25 000 GAS
21
COMPUTER SHOP
34 000 CONTROLLER
20
ABITI BELLA
ABITI BELLA
COMPUTER SHOP
TELEFONO
CELLULARE
88 000 GAS
WHERE
La clausola WHERE serve per implementare delle condizioni verificabili a
livello delle singole righe.
Questa clausola abbastanza semplice da usare ed gi stata utilizzata
precedentemente in questo corso, vediamo un esempio:
SELECT * FROM ASSEGNI
WHERE IMPORTO < 150000;
ASSEGNO
BENEFICIARIO
IMPORTO
NOTE
----------------- --------------------------------- ----------------- --------------------------------------------1
COMPUTER SHOP
BIOGAS SRL
88 000 GAS
17
GAS S.P.A.
25 000 GAS
21
COMPUTER SHOP
34 000 CONTROLLER
20
ABITI BELLA
COMPUTER SHOP
ABITI BELLA
ABITI BELLA
16
ASSICURAZIONI ASSO
BIOGAS SRL
COMPUTER SHOP
COMPUTER SHOP
200 000
COMPUTER SHOP
21
COMPUTER SHOP
34 000 CONTROLLER
17
GAS S.P.A.
25 000 GAS
LIBRERIE CULTURA
SUPERMARCHET GS
88 000 GAS
50 000 DISCHETTI E CD-ROM
TELEFONO
CELLULARE
SELECT *
FROM ASSEGNI
ORDER BY BENEFICIARIO DESC;
IMPORTO
NOTE
ASSEGNO
BENEFICIARIO
----------------- ---------------------------------- ----------------- -------------------------------------------5
SUPERMARCHET GS
LIBRERIE CULTURA
17
GAS S.P.A.
COMPUTER SHOP
21
COMPUTER SHOP
COMPUTER SHOP
200 000
COMPUTER SHOP
BIOGAS SRL
16
ASSICURAZIONI ASSO
20
ABITI BELLA
ABITI BELLA
25 000 GAS
50 000 DISCHETTI E CD-ROM
34 000 CONTROLLER
TELEFONO
CELLULARE
88 000 GAS
NOTE
-------------
ABITI BELLA
COMPLETO
DONNA
ABITI BELLA
PANTALONI
ASSICURAZIONI
ASSO
ASSICURAZIONE
CASA
BIOGAS SRL
GAS
CONTROLLER
COMPUTER SHOP
COMPUTER SHOP
DISCHETTI E CDROM
JOYSTICK
COMPUTER SHOP
COMPUTER SHOP
TELEFONO
CELLULARE
GAS
GAS S.P.A.
LIBRERIE CULTURA
LIBRI,
CANCELLERIA
SUPERMARCHET GS ALIMENTARI
NOTE
----------------------
ABITI BELLA
PANTALONI
ABITI BELLA
COMPLETO
DONNA
ASSICURAZIONI
ASSO
ASSICURAZIONE
CASA
BIOGAS SRL
GAS
COMPUTER SHOP
TELEFONO
CELLULARE
COMPUTER SHOP
JOYSTICK
COMPUTER SHOP
DISCHETTI E CDROM
COMPUTER SHOP
CONTROLLER
GAS S.P.A.
GAS
LIBRERIE CULTURA
LIBRI,
CANCELLERIA
SUPERMARCHET GS
ALIMENTARI
SELECT *
FROM ASSEGNI
ORDER BY 3;
BENEFICIARIO
IMPORTO
NOTE
ASSEGNO
----------------- ---------------------------------- ----------------- -------------------------------------------17
GAS S.P.A.
25 000 GAS
21
COMPUTER SHOP
34 000 CONTROLLER
COMPUTER SHOP
BIOGAS SRL
20
ABITI BELLA
COMPUTER SHOP
SUPERMARCHET GS
COMPUTER SHOP
200 000
ABITI BELLA
LIBRERIE CULTURA
16
ASSICURAZIONI ASSO
TELEFONO
CELLULARE
I dati sono stati visualizzati ordinandoli per il campo IMPORTO che appunto
il terzo campo che appare nella tabella ASSEGNI.
GROUP BY
Questa clausola ci permette di formare dei sottoinsiemi per quelle colonne
specificate. Vediamo cosa significa quanto affermato.
SELECT BENEFICIARIO
FROM ASSEGNI
GROUP BY BENEFICIARIO;
BENEFICIARIO
-------------------------------------ABITI BELLA
ASSICURAZIONI ASSO
BIOGAS SRL
COMPUTER SHOP
GAS S.P.A.
LIBRERIE CULTURA
SUPERMARCHET GS
Il risultato della query una lista di beneficiari, che appaiono per una sola
volta, anche se nella tabella di origine la maggior parte di essi compare pi
volte.
Questa clausola usata molto spesso per applicare le funzioni di gruppo non
a tutte le righe indistintamente, ma a sottoinsiemi di esse. Vediamo un
esempio:
Vogliamo sapere quanto stato elargito, in totale, per ogni beneficiario:
SELECT BENEFICIARIO, SUM(IMPORTO)
FROM ASSEGNI
GROUP BY BENEFICIARIO;
BENEFICIARIO
SUM(IMPORTO)
--------------------------------- ------------------------------ABITI BELLA
334 000
ASSICURAZIONI ASSO
425 000
BIOGAS SRL
88 000
COMPUTER SHOP
418 000
GAS S.P.A.
25 000
LIBRERIE CULTURA
245 000
SUPERMARCHET GS
150 000
ABITI BELLA
79 000 PANTALONI
23
BIOGAS SRL
24
LIBRERIE CULTURA
224 000
25
COMPUTER SHOP
LIBRI,
CANCELLERIA
88 000 CONTROLLER
ASSEGNI
IMPORTO
ASSEGNO
BENEFICIARIO
NOTE
----------------- ---------------------------------- ----------------- -------------------------------------------1
COMPUTER SHOP
LIBRERIE CULTURA
COMPUTER SHOP
200 000
BIOGAS SRL
SUPERMARCHET GS
16
ASSICURAZIONI ASSO
17
GAS S.P.A.
25 000 GAS
21
COMPUTER SHOP
34 000 CONTROLLER
20
ABITI BELLA
ABITI BELLA
COMPUTER SHOP
22
ABITI BELLA
23
BIOGAS SRL
24
LIBRERIE CULTURA
25
COMPUTER SHOP
TELEFONO
CELLULARE
88 000 GAS
79 000 PANTALONI
88 000 CONTROLLER
NOTE
-----------------------
ABITI BELLA
COMPLETO DONNA
ABITI BELLA
PANTALONI
ASSICURAZIONI ASSO
ASSICURAZIONE
CASA
BIOGAS SRL
GAS
COMPUTER SHOP
CONTROLLER
COMPUTER SHOP
DISCHETTI E CD-ROM
JOYSTICK
COMPUTER SHOP
TELEFONO
CELLULARE
COMPUTER SHOP
GAS
GAS S.P.A.
LIBRI, CANCELLERIA
LIBRERIE CULTURA
ALIMENTARI
SUPERMARCHET GS
413 000
ASSICURAZIONI
ASSO
425 000
BIOGAS SRL
487 000
COMPUTER
SHOP
506 000
25 000
LIBRERIE
CULTURA
469 000
SUPERMARCHET
GS
150 000
GAS S.P.A.
Abiti Bella compare nella tabella tre volte, Assicurazioni ASSO una volta, ecc.
Voglio sapere il totale dell'importo per ogni nota che facendo parte dello
stesso beneficiario compaia una o pi volte. Voglio sapere quante volte
quella stessa nota appare per lo stesso beneficiario. Voglio inoltre
visualizzare le note:
SELECT BENEFICIARIO, NOTE, SUM(IMPORTO),
COUNT(BENEFICIARIO)
FROM ASSEGNI
GROUP BY BENEFICIARIO, NOTE;
BENEFICIARIO
------------------------
NOTE
---------------------------
ABITI BELLA
COMPLETO
DONNA
224 000
ABITI BELLA
PANTALONI
189 000
ASSICURAZIONI
ASSO
ASSICURAZIONE
CASA
425 000
BIOGAS SRL
GAS
487 000
COMPUTER
SHOP
CONTROLLER
122 000
COMPUTER
SHOP
DISCHETTI E
CD-ROM
50 000
COMPUTER
SHOP
JOYSTICK
134 000
COMPUTER
SHOP
TELEFONO
CELLULARE
200 000
GAS S.P.A.
GAS
25 000
LIBRERIE
CULTURA
LIBRI,
CANCELLERIA
469 000
SUPERMARCHET
GS
ALIMENTARI
150 000
SUM(IMPORTO) COUNT(BENEFICIARIO)
---------------------- ---------------------------------
Nella prima riga della tabella estrapolata con la query precedente, vediamo
che COUNT(BENEFICIARIO) vale 1; ci significa che la nota 'Completo
donna' per quel beneficiario presente nella tabella di origine una sola volta.
Mentre invece, la nota 'Pantaloni', sempre per il medesimo beneficiario vale
2, questo significa che quella nota per quel beneficiario presente nella
tabella ben due volte.
Adesso vogliamo estrapolare i stessi dati della query precedente, ma
ordinandoli per le note.
NOTE
---------------------------
SUPERMARCHET
GS
ALIMENTARI
150 000
ASSICURAZIONI
ASSO
ASSICURAZIONE
CASA
425 000
ABITI BELLA
COMPLETO
DONNA
224 000
COMPUTER
SHOP
CONTROLLER
122 000
COMPUTER
SHOP
DISCHETTI E
CD-ROM
50 000
BIOGAS SRL
GAS
487 000
GAS S.P.A.
GAS
25 000
COMPUTER
SHOP
JOYSTICK
134 000
LIBRERIE
CULTURA
LIBRI,
CANCELLERIA
469 000
ABITI BELLA
PANTALONI
189 000
COMPUTER
SHOP
TELEFONO
CELLULARE
200 000
SUM(IMPORTO) COUNT(BENEFICIARIO)
---------------------- ---------------------------------
Per gli esempi futuri faremo riferimento alla tabella DIPENDENTI sottostante:
DIPENDENTI
NOME
DIVISIONE
STIPENDIO GIORNI_MUTUA FERIE_GODUTE
----------------- ---------------------------- ---------------- ----------------------- ---------------------------ROSSI
VENDITE
2 000 000
33
BIANCHI
VENDITE
2 100 000
BRUNI
RICERCA
3 300 000
VERDI
ACQUISTI
1 800 000
32
20
GIALLI
RICERCA
4 800 000
NERI
RICERCA
3 400 000
AMMINISTRAZIONE
2 400 000
24
VENDITE
2 000 000
99
12
MANCINI
MARCHETT
I
HAVING
Abbiamo visto come tramite la clausola GROUP BY le righe possano venire
raggruppate in sottoinsiemi. Una particolare interrogazione pu avere la
necessit di estrapolare solo quei sottoinsiemi di righe che soddisfano certe
condizioni, in questo caso per non possibile usare la clausola WHERE in
quanto tale clausola verifica la condizione che la segue, su tutte le righe e
non in maniera singola sui valori estrapolati per ogni sottoinsieme di righe.
Vediamo un esempio:
Vogliamo conoscere le medie dei stipendi per ogni divisione che superano i
2.200.000 di lire
SELECT DIVISIONE, AVG(STIPENDIO)
FROM DIPENDENTI
GROUP BY DIVISIONE
WHERE AVG(STIPENDIO) > 2200000;
ERRORE alla riga 4:
ORA-00933: comando SQL terminato erroneamente
Nella query scritta sopra possiamo vedere come la clausola WHERE sia stata
posta per ultima, infatti bisogna verificare la condizione solo dopo che sono
stati formati i sottoinsiemi dalla clausola GROUP BY.
Il risultato per, comunque un avviso di errore, proprio perch non
possibile utilizzare WHERE per verificare condizioni sui risultati di funzioni di
gruppo. Vediamo quindi come possiamo risolvere il problema:
SELECT DIVISIONE, AVG(STIPENDIO)
FROM DIPENDENTI
HAVING AVG(STIPENDIO) > 2200000;
DIVISIONE
AVG(STIPENDIO)
------------------------------ -------------------------AMMINISTRAZIONE
2 400 000
RICERCA
3 833 333,3
2033333,3
In questo caso stata estrapolata la media degli stipendi della sola divisione
vendite. Proviamo a ottenere lo stesso risultato usando a posto della clausola
HAVING la clausola WHERE:
SELECT DIVISIONE, AVG(STIPENDIO)
FROM DIPENDENTI
GROUP BY DIVISIONE
WHERE DIVISIONE = 'VENDITE';
ERRORE alla riga 4:
ORA-00933: comando SQL terminato erroneamente
2033333,3
In questo caso la clausola WHERE stata usata non sugli insiemi delle righe,
in quanto posta prima della clausola GROUP BY.
Voglio conoscere la media dei giorni di ferie godute per dipartimento, ma solo
di quei dipendenti che percepiscono stipendi superiori ai 2.050.000 di lire:
SELECT DIVISIONE, AVG(FERIE_GODUTE)
FROM DIPENDENTI
WHERE STIPENDIO > 2050000
GROUP BY DIVISIONE;
DIVISIONE
-----------------------
AVG
(FERIE_GODUTE)
--------------------------------------
AMMINISTRAZIONE 24
RICERCA
3,3333333
VENDITE
DIVISIONE
-----------------------
AVG
(FERIE_GODUTE)
--------------------------------------
AMMINISTRAZIONE 24
RICERCA
3,3333333
Riepilogo
Dagli esempi precedenti, dalle cose che sono state dette e da eventuali
esperimenti che potremmo fare, possiamo enunciare degli assiomi che
riguardano l'uso delle clausole viste in questo capitolo:
VENDITE
2 000 000
33
BIANCHI
VENDITE
2 100 000
BRUNI
RICERCA
3 300 000
VERDI
ACQUISTI
1 800 000
32
20
GIALLI
NERI
RICERCA
4 800 000
RICERCA
3 400 000
AMMINISTRAZIONE
2 400 000
24
VENDITE
2 000 000
99
12
MANCINI
MARCHETT
I
COMPUTER SHOP
LIBRERIE CULTURA
COMPUTER SHOP
200 000
BIOGAS SRL
SUPERMARCHET GS
16
ASSICURAZIONI ASSO
17
GAS S.P.A.
25 000 GAS
21
COMPUTER SHOP
34 000 CONTROLLER
20
ABITI BELLA
ABITI BELLA
COMPUTER SHOP
TELEFONO
CELLULARE
88 000 GAS
Capitolo 5
Join - Combinazione di tabelle
Questo capitolo tratta un importante tipo di operazione tra le tabelle: il Join.
Il vocabolo join significa unione e nel caso di SQL sta ad indicare unione tra
tabelle. Esistono vari tipi di join, ma tutti derivano o possono essere ricondotti
a vari operatori dell'algebra insiemistica. L'importanza principale del join
risiede nella possibilit che ci offre per correlare e visualizzare dati
appartenenti a tabelle diverse o alla medesima tabella, logicamente correlati
tra di loro. I semplici dati, da noi uniti, possono assumere la forma di
complesse informazioni cos come noi li vogliamo.
CROSS JOIN
Per comprendere a pieno l'operazione CROSS JOIN (unione incrociata)
bisogna aver ben chiaro il concetto di prodotto cartesiano:
........................................................... Prodotto
cartesiano...........................................................
Dati due insiemi D1 e D2 si chiama prodotto cartesiano di D1 e D2, l'insieme
delle coppie ordinate (v1, v2), tali che v1 un elemento di D1 e v2 un
elemento di D2.
Vediamo cosa significa quanto affermato con un esempio:
A x B = {(2, r), (2, s), (2, d), (2, 4), (f, r), (f, s), (f, d), (f, 4), (r, r), (r, s), (r, d), (r,
4)}
Come possiamo vedere il prodotto cartesiano fra i due insiemi dato da tutti
gli elementi di A combinati con ogni elemento di B. Nella rappresentazione
delle varie coppie dobbiamo rispettare l'ordine di apparizione degli elementi,
in quanto l'appartenenza dell'elemento all'insieme individuabile proprio
dalla suo ordine di apparizione. Nell'esempio abbiamo usato solo due insiemi
ma il prodotto cartesiano applicabile anche a pi di due insiemi.
...........................................................................................................................
..................
Ora considerando che le tabelle non sono altro che insiemi i cui elementi
sono le righe ecco che possiamo individuare l'operazione di CROSS JOIN in
quella di prodotto cartesiano appartenente alle teorie degli insiemi. Dunque il
prodotto cartesiano tra due o pi tabelle si traduce in una istruzione chiamata
CROSS JOIN. Il CROSS JOIN si ottiene in maniera molto semplice
elencando dopo la FROM le tabelle che devono essere coinvolte. Vediamo
un esempio di CROSS JOIN:
Per lo scopo usiamo due tabelle: TAB1 e TAB2
TAB1
TAB2
COLONTAB1
-------------------------------
COLONTAB2
-------------------------------
RIG1 TAB1
RIG1 TAB2
RIG2 TAB1
RIG2 TAB2
RIG3 TAB1
RIG3 TAB2
RIG4 TAB1
RIG5 TAB1
SELECT *
FROM TAB1, TAB2;
COLONTAB1
---------------------------
COLONTAB2
---------------------------
RIG1 TAB1
RIG1 TAB2
RIG2 TAB1
RIG1 TAB2
RIG3 TAB1
RIG1 TAB2
RIG4 TAB1
RIG1 TAB2
RIG5 TAB1
RIG1 TAB2
RIG1 TAB1
RIG2 TAB2
RIG2 TAB1
RIG2 TAB2
RIG3 TAB1
RIG2 TAB2
RIG4 TAB1
RIG2 TAB2
RIG5 TAB1
RIG2 TAB2
RIG1 TAB1
RIG3 TAB2
RIG2 TAB1
RIG3 TAB2
RIG3 TAB1
RIG3 TAB2
RIG3 TAB2
RIG4 TAB1
RIG3 TAB2
RIG5 TAB1
Questo il risultato che si ottiene dal CROSS JOIN delle tabelle TAB1 e
TAB2, come si pu vedere non altro che un prodotto cartesiano.
Chiaramente avremmo potuto usare anche pi di due tabelle.
Il CROSS JOIN non particolarmente utile e viene usato raramente, ma se in
una CROSS JOIN si utilizza la clausola WHERE potremmo ottenere join
molto pi interessanti.
NATURAL JOIN
Il NATURAL JOIN un tipo di operazione che ci permette di correlare due o
pi tabelle sulla base di valori uguali in attributi contenenti lo stesso tipo di
dati.
Vediamo un esempio:
Per lo scopo usiamo due tabelle: PERSONE e AUTO. La tabella AUTO fa
riferimento alla persona proprietaria dell'auto attraverso il campo
PROPRIETARIO in cui sono riportati i numeri di patente. Lo stesso tipo di
dato presente nella tabella PERSONE nel campo PATENTE.
PERSONE
AUTO
NOME
PATENTE
----------------- ---------------------------
TARGA
----------------------
ANTONIO
123
VT AC73949
156
GIOVANNI
156
ROMA J1003
172
ARTURO
172
MI GH3434
300
NA G666223
301
PROPRIETARIO
-----------------------
Vogliamo ottenere un join delle righe delle due tabelle la dove i valori dei
campi PROPRIETARIO e PATENTE sono uguali .
SELECT *
FROM PERSONE, AUTO
WHERE PATENTE = PROPRIETARIO;
NOME
PATENTE
TARGA
------------------- -------------------- ----------------------
PROPRIETARIO
-----------------------
----
---
GIOVANNI
156
VT AC73949
156
172
ROMA J1003
172
ARTURO
Nel caso le due tabelle originarie avessero avuto i campi interessati al join
(PATENTE e PROPRIETARIO) con lo stesso nome in entrambe, avremmo
dovuto specificare dopo la WHERE prima del nome del campo il nome della
tabella a cui facevamo riferimento. Facciamo un esempio considerando le
tabelle PERSONE e AUTO cos modificate
PERSONE
AUTO
NOME
NUM_PATENTE
---------------- ----------------------------
TARGA
----------------------
NUM_PATENTE
-----------------------
ANTONIO
123
VT AC73949
156
GIOVANNI
156
ROMA J1003
172
ARTURO
172
MI GH3434
300
NA G666223
301
NUM_PATENTE
-----------------------
GIOVANNI
156
VT AC73949
156
ARTURO
172
ROMA J1003
172
INNER JOIN
un tipo di join in cui le righe delle tabelle vengono combinate solo se i
campi collegati con join soddisfano una determinata condizione.
Vediamo un esempio:
Vogliamo ottenere un join delle righe delle due tabelle PERSONE e AUTO, la
dove i valori dei campi PROPRIETARIO e PATENTE sono uguali e dove il
valore del campo NOME uguale ad 'ARTURO'.
SELECT *
FROM PERSONE, AUTO
WHERE PATENTE = PROPRIETARIO
AND NOME = 'ARTURO';
TARGA
NOME
PATENTE
------------------- -------------------- --------------------------ARTURO
172
ROMA J1003
PROPRIETARIO
----------------------172
PATENTE
172
TARGA
ROMA J1003
PROPRIETAR
172
PATENTE
TARGA
PROPRIETAR
GIOVANNI
156
VT AC73949
156
ARTURO
172
ROMA J1003
172
Possiamo renderci conto che questo tipo di join simile al natural join;
infatti il natural join un particolare caso di inner join.
OUTER JOIN
Con l'OUTER JOIN possibile estrapolare anche quei dati, appartenenti ad
una delle tabelle, che non verrebbero estrapolati nei tipi di join visti fino a
questo momento. Infatti OUTER significa esterno; dati esterni al normale tipo
di join.
Dobbiamo specificare quale la tabella di cui vogliamo estrapolare i dati
anche se non soddisfano la condizione di join, questo lo facciamo indicando
con LEFT o RIGHT se la tabella in questione quella che appare a destra o
a sinistra del comando JOIN.
SELECT . . .
FROM tabella1 [LEFT | RIGHT] JOIN tabella2
ON tabella1.campox condizione tabella2.campoy
Vediamo alcuni esempi:
Vogliamo visualizzare nel nostro JOIN oltre a tutte le persone che possiedono
un auto e l'auto appartenuta, anche quelle che non possiedono nessuna
auto:
SELECT *
FROM PERSONE LEFT JOIN AUTO
ON PERSONE.PATENTE = AUTO.PROPRIETARIO;
NOME
PATENTE
TARGA
PROPRIETAR
ANTONIO
123
GIOVANNI
156
VT AC73949
156
ARTURO
172
ROMA J1003
172
SELF JOIN
Il SELF JOIN ci consente di unire una tabella con se stessa. La sintassi
simile a quella della query vista nel paragrafo che trattava il CROSS JOIN.
Vediamo un esempio usando la tabella TAB2:
TAB2
COLONTAB2
------------------RIG1 TAB2
RIG2 TAB2
RIG3 TAB2
SELECT R1.COLONTAB2, R2.COLONTAB2
FROM TAB2 R1, TAB2 R2;
R1.COLONTAB2 R2.COLONTAB2
------------------------------------------------RIG1 TAB2
RIG1 TAB2
RIG2 TAB2
RIG1 TAB2
RIG3 TAB2
RIG1 TAB2
RIG1 TAB2
RIG2 TAB2
RIG2 TAB2
RIG2 TAB2
RIG3 TAB2
RIG2 TAB2
RIG1 TAB2
RIG3 TAB2
RIG2 TAB2
RIG3 TAB2
RIG3 TAB2
RIG3 TAB2
ID_PERSONA
NOME
CONIUGE SESSO
--------------------- ----------------- --------------- --------------------1
ANTONIO
12
12
SILVIA
GIULIO
MARIA
ROBERTA
ANTONELLA
ARTURO
SILVIA
ARTURO
ROBERTA
GIULIO
ANTONELLA
ROBERTA
ARTURO
SILVIA
ANTONIO
SELECT . . .
FROM PERSONE, UNIONE, CONTI-CORRENTI
WHERE PERSONE.ID-PERSONA = UNIONE.ID-PERSONA
AND UNIONE.ID-CONTI = CONTI-CORRENTI.ID-CONTI;
Alla select precedente nulla ci impedisce di aggiungere altre condizioni,
magari per poter visualizzare soltanto i conti appartenenti al Sig. Rossi
Antonio. Lascio al lettore il compito di aggiungere all'espressione l'ulteriore
condizione.
ESERCIZI (capitolo 5)
Nella tabella ISCRITTI sono presenti gli associati ad un club, nella tabella
FAMILIARI sono registrati gli appartenenti alla famiglia di ogni associato. Per
alcuni esercizi faremo riferimento a queste due tabelle.
ISCRITTI
NOME
MATRICOLA
GIOVANNI
ANTONIO
21
RICCARDO 9
FAMILIARI
NOME
GIULIA
FIGLIA
21
MARIA
MOGLIE
21
35
21
RUGERO FIGLIO
MODELLI
COD_CASA
NOME_AUTO
NOME_CASA
COD_CASA
STATO
TIPO
CITTA
CILINDRATA
Scrivere una select che restituisca come risultato il codice della casa, il nome
della casa, la citt e il nome delle auto per le automobili di tipo sport che
hanno una cilindrata compresa tra 1000 cc e 2000 cc, estremi inclusi.
5) Scrivere una select che restituisca come risultato, dalle tabelle
dell'esercizio N 4, il codice della casa e il nome della casa che produce pi
di due modelli di automobili di tipo sport. Utilizzare la 'tecnica' dell'unione fra
tabelle.
6) Date due tabelle (TABELLA1 e TABELLA2) che contengono una colonna
chiamata NUMERO, come fareste a trovare quei numeri che appartengono a
entrambe le tabelle? Scrivere una query.
7) Date le tabelle STUDENTI(matricola, nome_esame, voto),
MATRICOLA(matricola, cognome, nome)
scrivere una select che abbia come risultato il cognome e la matricola degli
studenti che hanno sostenuto l'esame di informatica riportando una votazione
compresa tra 23 e 28, oppure hanno sostenuto l'esame di informatica.
SOLUZIONI ESERCIZI CAPITOLO 5
1) Possiamo ottenere quanto richiesto utilizzando una delle seguenti select.
La seconda select utilizza usa una sintassi non implementabile tramite SQL
Plus 8.0; notiamo che i nomi dei campi specificati in ON sono preceduti dal
nome della tabella a cui appartengono.
Capitolo 6
Subquery
Se siamo in grado di padroneggiare con la maggior parte delle 'sintassi' viste
nei capitoli precedenti, siamo a buon punto e possiamo realizzare
interrogazioni molto complesse. Sebbene ci per, facile incappare in casi
in cui non possibile estrapolare i dati in maniera immediata e semplice. Per
VENDITE
2 000 000
33
BIANCHI
VENDITE
2 100 000
BRUNI
RICERCA
3 300 000
VERDI
ACQUISTI
1 800 000
32
20
GIALLI
RICERCA
4 800 000
NERI
RICERCA
3 400 000
MANCINI
AMMINISTRAZIONE
2 400 000
24
MARCHETT
I
VENDITE
2 000 000
99
12
Subquery con IN
Questo operatore ci consente di estrapolare dalla subquery non un solo
valore, ma pi valori da cui verr verificata la corrispondenza. Cerchiamo di
capire con un esempio questa sintassi:
ISCRITTI
NOME
MATRICOLA
GIOVANNI
ANTONIO
21
RICCARDO 9
FAMILIARI
NOME
GIULIA
FIGLIA
21
MARIA
MOGLIE
21
35
21
RUGERO FIGLIO
MATRICOLA
21
GIOVANNI 1
SELECT *
FROM ISCRITTI
WHERE MATRICOLA
IN
(SELECT MATRICOLA_DEL_PARENTE_ISCRITTO
FROM FAMILIARI
WHERE PARENTELA = 'FIGLIA');
NOME
MATRICOLA
ANTONIO 21
SELECT ID_AGENZIA
FROM UNIONE
WHERE TARGA IN (Q1)
AND TARIFFA < 100.000;
Questa query la chiamiamo Q2.
A questo punto abbiamo a disposizione i codici delle agenzie che soddisfano
il nostro quesito, ma non abbiamo ancora a disposizione i nomi di tali
agenzie. Inoltre i codici delle agenzie sono inutilmente ripetuti pi volte,
dunque la successiva query che soddisfa completamente il quesito :
SELECT NOME_AGENZIA
FROM AGENZIE
WHERE ID_AGENZIA IN (Q2);
Vediamo ora la query scritta in modo completo:
SELECT NOME_AGENZIA
FROM AGENZIE
WHERE ID_AGENZIA IN
(SELECT ID_AGENZIA
FROM UNIONE
WHERE TARGA IN
(SELECT TARGA
FROM AUTO
WHERE CATEGORIA = 'SPORT';)
AND TARIFFA < 100000;);
Considerando il modo in cui abbiamo costruito questa interrogazione,
possiamo renderci conto che la maniera migliore per effettuare la lettura e
comprensione di una query di questo tipo, iniziare ad analizzare le
subquery pi interne e man mano passare a quelle pi esterne. Questa
considerazione importante ed valida anche per la scrittura della query. In
quest'ultimo caso per, decidere quale sar la subquery pi interna difficile,
comunque sia dobbiamo affidarci non tanto a delle eventuali regole
assiomatiche, ma alla nostra logica che se utilizzata con rigore non pu
tradirci.
EXISTS
DIPENDENTI
NOME
DIVISIONE
STIPENDIO GIORNI_MUTUA FERIE_GODUTE
------------------------------------------------------------- -------------------------- ----------------------- --
ROSSI
BIANCHI
BRUNI
VERDI
GIALLI
NERI
VENDITE
2 000 000
33
VENDITE
2 100 000
RICERCA
3 300 000
ACQUISTI
1 800 000
32
20
RICERCA
4 800 000
RICERCA
3 400 000
AMMINISTRAZIONE
2 400 000
24
VENDITE
2 000 000
99
12
MANCINI
MARCHETT
I
VENDITE
BIANCHI
VENDITE
BRUNI
RICERCA
VERDI
ACQUISTI
GIALLI
RICERCA
NERI
RICERCA
MANCINI
AMMINISTRAZIONE
MARCHETT
I
VENDITE
Questi tre operatori svolgono funzioni simili alle parole chiave IN e EXSIST.
Si consiglia di consultare altro testo per approfondire l'argomento.
ESERCIZI (capitolo 6)
1) La seguente query giusta? e se errata perch?
SELECT COGNOME, NOME, MATRICOLA, ETA
FROM DIPENDENTI
WHERE (SELECT AVG(ETA) FROM DIPENDENTI) < ETA;
2) La seguente query giusta? e se errata perch?
SELECT MATRICOLA
FROM DIPENDENTI
WHERE ETA > (SELECT ETA FROM DIPENDENTI);
3) Dalla tabella PERSONE scrivere una interrogazione che estrapoli tutti i dati
delle persone che possiedono almeno un'auto. Usare la tecnica delle
subquery.
PERSONE
NOME
AUTO
PATENTE
TARGA
PROPRIETARIO
ANTONIO
123
VT
AC73949
156
GIOVANNI
156
ROMA
J1003
172
ARTURO
172
MI
GH3434
300
NA
G666223
301
4) Nella tabella ISCRITTI sono presenti gli associati ad un club, nella tabella
FAMILIARI sono registrati gli appartenenti alla famiglia di ogni associato;
ISCRITTI
NOME
MATRICOLA
GIOVANNI
ANTONIO
21
RICCARDO 9
FAMILIARI
NOME
GIULIA
FIGLIA
21
MARIA
MOGLIE
21
35
21
RUGERO FIGLIO
scrivere una select che dalle tabelle ISCRITTI e FAMILIARI, ci visualizzi gli
iscritti che non hanno
nessun familiare.
5) La tabella MARCHE contiene dati riguardanti le industrie costruttrici di
automobili; la tabella MODELLI
contiene dati riguardanti i vari modelli di auto esistenti. I nomi dei campi in
neretto rappresentano le
chiavi primarie.
MARCHE
MODELLI
COD_CASA
NOME_AUTO
NOME_CASA
COD_CASA
STATO
TIPO
CITTA
CILINDRATA
Scrivere una select che restituisca come risultato il codice della casa e il
nome della casa che produce pi di due modelli di automobili di tipo sport.
Utilizzare la 'tecnica' delle subquery.
6) Data una tabella STUDENTI(matricola, esame, voto), scrivere una query
che abbia come risultato la
matricola degli studenti che hanno effettuato pi esami dello studente
matricola 23.
SOLUZIONI ESERCIZI CAPITOLO 6
1) la query sbagliata perch la subquery appare a sinistra.
2) la query sbagliata perch la subquery restituisce una serie di valori e non
un solo valore.
3)
SELECT *
FROM PERSONE
WHERE PATENTE IN
(SELECT PROPRIETARIO
FROM AUTO;);
4)
SELECT NOME
FROM ISCRITTI
WHERE MATRICOLA NOT IN
(SELECT MATRICOLA_DEL_PARENTE_ISCRITTO
FROM FAMILIARI);
5)
SELECT COD_CASA, NOME_CASA
FROM MARCHE
WHERE COD_CASA IN
(SELECT COD_CASA
FROM MODELLI
WHERE TIPO = 'SPORT'
GROUP BY COD_CASA
HAVING COUNT(*) > 2 ;);
6)
SELECT MATRICOLA
FROM ESAMI
GROUP BY MATRICOLA
HAVING COUNT(*) >
(SELECT COUNT(*)
FROM ESAMI
WHERE MATRICOLA = "23";);
Capitolo 7
Manipolare i dati
Fino a questo punto del corso abbiamo trattato quella parte di SQL che
assolve alle funzioni di QL (Query Language) ovvero interrogazioni dei dati
senza nessuna possibilit di manipolarli come ad esempio cambiarne il
valore. In questo capitolo vedremo invece quella parte di SQL che assolve
Nome
Citta
Giovanni
Verdi
Via Bella
Roma
Antonio
Rossi
Via Casalacio
Roma
GIOCATORI
Nome
Cognome
Mancini
Arturo
Squadra
S. Lorenzo
Nome
Mancini
Arturo
Verdi
Giovanni
Rossi
Antonio
Squadra
S. Lorenzo
NOME
DIRIGENTI
NOME
MANSIONE
ROSSI
MARIO
RAGIONIERE
NERI
GIULIO
DIRIGENTE
BIANCHI
MARIA
IMPIEGATO
VERDI
LUIGI
DIRETTORE
COGNOME
NOME
DIRIGENTI
MANSIONE
NOME
GIULIO
ROSSI
MARIO
RAGIONIERE
NERI
GIULIO
DIRIGENTE
BIANCHI
MARIA
IMPIEGATO
VERDI
LUIGI
DIRETTORE
COGNOME
NERI
La insert dell'esempio precedente era di tipo selettivo, vediamo ora una insert
di tipo globale: Supponiamo di avere la necessit di inserire nella tabella
DIRIGENTI un nuovo dirigente il cui nominativo non presente nella tabella
DIPENDENTI in quanto il dirigente in questione non un dipendente ma un
libero professionista 'assoldato' dall'azienda.
INSERT INTO DIRIGENTI
VALUES ('GIOVANNI', 'GIOVANNETTI');
NOME
DIRIGENTI
COGNOME
NERI
GIULIO
GIOVANNI GIOVANNETTI
NOME
MANSIONE
ROSSI
MARIO
RAGIONIERE
NERI
GIULIO
DIRIGENTE
BIANCHI
MARIA
IMPIEGATO
VERDI
LUIGI
DIRETTORE
VESPUCCI
AMERIGO
Una importante differenza tra i due tipi di insert che tramite l'insert con value si
inserisce un record per volta, mentre tramite insert con la select possibile inserire
molti record alla volta.
come chiave primaria; infatti possibile far si che ad ogni nuovo inserimento
di record, viene immesso un valore incrementale che univoco.
In Access per ottenere tutto ci basta dichiarare un campo di tipo contatore e
questo automaticamente, ad ogni inserimento di record, si caricher di un
valore incrementato di una unit. Quindi per il primo record avremo il valore
1, per il secondo il valore 2 e cos via.
In Oracle il discorso pi complesso, infatti bisogna creare una sequenza e
poi permettere che questa generi un valore incrementale da immettere nel
campo. Vediamo un esempio di come si crea una sequenza e di come si
utilizza:
CREATE SEQUENCE sq_atleti /* Viene creata una sequenza di nome sq_atleti */
INCREMENT BY 1 /* L'incremento della sequenza unitario */
START WITH 1 /*Il primo valore della sequenza sar 1 */
NOMAXVALUE /* Non deve esistere un valore massimo oltre il quale non si
possono generare valori */
NOCYCLE /*Non permette che i valori vengano generati da capo in un nuovo ciclo
*/
NOCACHE /* Non permette di preallocare i valori della sequenza in memoria */
ORDER; /* Garantisce che i numeri della sequenza vengano assegnati alle istanze
che li richiedono
incrementele */
UPDATE
Questa istruzione serve per modificare i dati contenuti in una tabella.
Consideriamo di avere una tabella PRODOTTI con i campi prodotto e prezzo;
ora vogliamo modificare i corrispettivi prezzi dei prodotti aumentandoli del
10%:
Tabella prima dell'update:
PRODOTTI
PRODOTTO
PREZZO
MARMELLATA L. 3.000
CIOCCOLATA L. 4.500
BISCOTTI
L. 2.500
UPDATE PRODOTTI
SET PREZZO = PREZZO * 1.10;
Tabella dopo l'update:
PRODOTTI
PRODOTTO
PREZZO
MARMELLATA L. 3.300
CIOCCOLATA L. 4.950
BISCOTTI
L. 2.750
PREZZO
MARMELLATA L. 3.300
CIOCCOLATA L. 5.099
BISCOTTI
L. 2.750
PRODOTTI
PRODOTTO
PREZZO
MARMELLATA L. 3.300
NUTELLA
L. 5.864
BISCOTTI
L. 2.750
DELETE
Oltre a inserire dati in una tabella o modificarli, occorre anche poterli
cancellare. Questa istruzione assolve allo scopo. Va fatto notare che
DELETE non cancella un singolo campo per volta ma una riga o pi righe per
volta; inoltre questa istruzione cancella i record e non l'intera tabella.
Vediamo ora alcuni esempi per meglio comprendere come funziona DELETE.
Si da il caso che dalla tabella PRODOTTI si voglia cancellare la riga della
marmellata:
DELETE FROM PRODOTTI
WHERE PRODOTTO = 'MARMELLATA';
Tabella dopo la delete:
PRODOTTI
PRODOTTO
PREZZO
NUTELLA
L. 5.864
BISCOTTI
L. 2.750
Si da il caso che, ancora non contenti di aver cancellato la sola riga della
marmellata, ora vogliamo cancellare tutte le dighe della tabella:
DELETE FROM PRODOTTI;
PRODOTTI
PRODOTTO
PREZZO
ROLLBACK, COMMIT
Per le sintassi di questi comandi si fatto riferimento al tool SQL Plus 8.0 di
Oracle. Tali comandi non sono implementati da Access.
Quando si inseriscono o si cancellano o si modificano i dati in un database
possibile intervenire al fine di annullare l'operazione o confermarla
definitivamente. Ci particolarmente utile quando ci accorgiamo di aver
eseguito uno dei tre comandi, visti in questo capitolo, sui dati errati, o quando
vogliamo confermare definitivamente il comando mandato in esecuzione.
Per far maggiore chiarezza a quanto affermato va detto che i DBMS i quali
implementano i comandi ROLLBACK e COMMIT, non rendono effettivi
istantaneamente i comandi DELETE, UPDATE e INSERT, ma tengono
memoria temporaneamente delle modifiche effettuate in un'altra area. Questo
fa si che un utente, che non sia quello che ha eseguito uno dei comandi
DELETE, UPDATE e INSERT, non veda le modifiche appartate; mentre
l'altro, quello che ha eseguito uno dei tre comandi, veda le tabelle in oggetto
come se fossero state modificate definitivamente. Dunque il comando di
COMMIT rende definitive le modifiche apportate e il comando ROLLBACK
elimina ogni modifica da queste ultime. Cerchiamo di meglio comprendere di
quanto detto:
COMMIT esplicito
Rappresenta il comando vero e proprio che l'utente digita per confermare e
rendere definitive le modifiche apportate. La sintassi la seguente e va
digitata dopo aver mandato in esecuzione uno o pi dei tre comandi visti in
questo capitolo.
COMMIT;
COMMIT implicito
Ci sono delle azioni che mandano in esecuzione il COMMIT in maniera
automatica. Una di queste azioni ad esempio l'uscita dal tool che ci
consente di mandare in esecuzione le sintassi SQL o eseguire dei seguenti
comandi: CREATE TABLE, CREATE VIEW, DROP TABLE, DROP VIEW. Ci
sono altri comandi o azioni che provocano il COMMIT; per ulteriori
Capitolo 8
Creare e mantenere tabelle
Il capitolo precedente era dedicato a quella parte di SQL che assolve alle
funzioni di DML (Data Manipulation Language). In questo capitolo tratteremo
invece, quella parte di SQL che implementa le funzioni di DDL (Data
Description Language) ovvero quelle funzioni che ci permettono di progettare,
di manipolare e di distruggere quelle strutture che contengono i dati.
L'acronimo Description infatti, sta a indicare 'descrizione' o meglio
'definizione' delle strutture che conterranno i dati.
Vedremo in dettaglio le istruzioni CREATE TABLE, ALTER TABLE, DROP
TABLE, per creare, modificare ed eliminare tabelle. Esistono anche i comandi
CREATE DATABASE e DROP DATABASE per creare e distruggere
database; questi comandi per non verranno mostrati in questo corso in
quanto la loro implementazione varia notevolmente da un DBMS ad un altro.
Inoltre tutti i DBMS, oggi in commercio, hanno dei tools di tipo grafico che
permettono di creare e di distruggere un database in modo facile e senza
scrivere codice SQL.
CREATE TABLE
Questa istruzione, come facilmente si immagina, serve a creare una tabella; il
suo schema sintattico il seguente:
CREATE TABLE nomeTabella
(
campo1 tipoDati [valore di default] [vincoli],
campo2 tipoDati [valore di default] [vincoli],
campo3 tipoDati [valore di default] [vincoli],
........................
);
Vediamo un esempio:
CREATE TABLE ANAGRAFICA
(
NOME VACHAR2(25),
COGNOME VARCHAR2(25),
DATA_NASCITA DATE
);
ANAGRAFICA
NOME
COGNOME
DATA_NASCITA
CHAR
DATE
LONG
LONG RAW Dati binari (grafici, suoni, video, ecc.) fino a 2 gigabyte.
NUMBER
RAW
ROWID
NOT NULL
In un campo dichiarato con il vincolo NOT NUILL non possibile non inserire
un valore. Se non inseriamo un valore valido in un campo di questo tipo i
valori inseriti nella riga non vengono accettati. Facciamo un esempio:
Vogliamo creare una tabella di nome di TIFOSI con i campi:
IDENTIFICATIVO, NOME, SQUDRA. Il campo IDENTIFICATIVO deve
contenere obbligatoriamente un valore.
CREATE TABLE TIFOSI
(
IDENTIFICATIVO CHAR(9) NOT NULL,
NOME VARCHAR2(25),
SQUADRA VARCHAR2(25)
);
TIFOSI
NOME
IDENTIFICATIVO
SQUADRA
NOME
COGNOME
NOME
GIOVANNI
MARIA
MARIA
capogruppo
NUMBER CHECK (capogruppo IN (0,1)), /* Permette
l'inserimento dei soli valori 0 o 1 */
dal
DATE NOT NULL
);
CREATE TABLE indirizzi_elettronici (
rif_indirizzo
NUMBER,
tipo
CHAR(1) CHECK (tipo in ('E','W')), /* Permette
l'inserimento dei soli caratteri 'E' o 'W' */
address
VARCHAR2(80)
CREATE TABLE classi_di_rischio0 (
id_classe
NUMBER(3) CHECK (id_classe >= 900), /*
Permette l'inserimento solo se verificata la condizione */
descrizione
VARCHAR2(100),
stato
CHAR(1) CHECK (stato IN ('A','D'))
);
CREATE TABLE tipi_di_rischio0 (
id_classe
NUMBER(3) NOT NULL,
id_tipo_rischio
NUMBER(3) CHECK (id_tipo_rischio >= 1 AND
id_tipo_rischio < 900),
descrizione
VARCHAR2(100),
premio_minimo
NUMBER,
durata_minima
NUMBER,
NUMBER,
proroga_minima
NUMBER,
tasso_grandi_clienti
tasso_clienti_medi
NUMBER,
tasso_clienti_base
NUMBER,
coefficienti_autonomia NUMBER,
numero_appendice
NUMBER,
stato_rischio
CHAR(2) CHECK (stato_rischio IN
('RO','RN','RS')),
stato
CHAR(1) CHECK (stato IN ('A','D')),
dal
DATE NOT NULL
);
La parola chiave CHECK non implementata da Access.
Supponiamo ora che alla tabella DIRIGENTI vogliamo modificare il tipo del
campo TITOLO_STUDIO che un CHAR(30) in CHAR(60):
ALTER
DIRIGENTI CHAR(60);
MODIFYTABLE
TITOLO_STUDIO
Access */
una volta lanciata questa ALTER TABLE non sar pi possibile inserire un
valore numerico nel campo residuo maggiore del valore presente nel campo
importante utilizzare sempre questa sintassi per non correre il grave rischio
di cancellare la tabella sbagliata.
Capitolo 9
VIEW e INDICI
Le view e gli indici sono oggetti abbastanza diversi tra di loro; le view
esistono in RAM, gli indici vengono memorizzati su disco. Malgrado questa
sostanziale differenza, i due oggetti, hanno in comune il fatto di essere
associati a una o pi tabelle e di mostrarci i dati in un ordine o formato
diverso da quello originale. Cerchiamo di capire meglio di cosa si tratta.
VIEW
Fino a questo punto del corso abbiamo utilizzato oggetti (database, tabelle e
campi) che avevano la caratteristica di esistere fisicamente su disco. In
questo paragrafo invece andremo a considerare qualcosa che non esiste
fisicamente su disco. Questo particolare oggetto ogni volta ricostruito in
RAM, ma come se esistesse fisicamente su disco. Infatti pu essere
trattato, a parte qualche piccola limitazione, come se fosse una tabella vera e
propria.
Le VIEW vengono create mediante l'istruzione CREATE VIEW associandogli
un nome ed una lista di attributi. I valori presenti nelle VIEW possono essere
modificati o estrapolati da i comuni comandi applicabili alle tabelle. Vediamo
quali sono questi comandi:
SELECT
INSERT
INPUT
UPDATE
DELETE
DROP
Le VIEW possono anche essere usate per creare query complesse; una volta
creata la VIEW su di essa possibile eseguire query. Le modifiche dei dati su
una VIEW si ripercuotono su tutte le tabelle da cui sono state create e
viceversa.
Per creare le VIEW useremo la seguente sintassi:
CREATE VIEW nomeView [(colonna1, colonna2, . . . )] AS
SELECT nomi_delle_colonne
FROM . . .
...;
Proteggere i dati:
Uno dei grossi problemi dei database la sicurezza e la riservatezza
dei dati. Le viste ci aiutano ad ottenere questo scopo: si immagini di
avere una certa tabella a cui non vogliamo che un certo tipo di utenza
possa accedere a tutti i campi indistintamente.
Per questo tipo di utenza creeremo una vista in cui appariranno soltanto
alcuni dei campi, della tabella in questione.
Convertire le unit di misura:
Ad esempio se il campo IMPORTO contenente valori espressi in
sterline e vogliamo visualizzarli in lire l'uso di una VIEW risulta essere
particolarmente utile. Vediamo un esempio:
CREATE VIEW fattureRegnoUnito (azienda, lire) AS
INDICI
Provate ad immaginare un biblioteca dove esistono lunghe cassettiere
contenenti migliaia di schede ordinate alfabeticamente per titolo, con i dati di
ogni singolo libro. Supponete che il bibliotecario in un attimo di follia le lanci
tutte in aria e poi le riponga a caso nelle cassettiere. Ora per ritrovare la
scheda di un qualsiasi libro dovremo sfogliare le schede una per una fino a
trovare il titolo che ci interessava. Mediamente, se le schede sono 1.000.000
dovremmo sfogliare e leggere l'intestazione (titolo del libro) di 500.000
schede prima di trovare quella giusta. Ci che stato descritto quello che
accade quando un qualsiasi DBMS cerca un record in una tabella senza
usare gli indici; infatti i record all'interno di una tabella rispettano l'ordine di
inserimento e non quello alfabetico. Immaginate ora che il bibliotecario non
voglia pi riordinare le schede, ma comunque decida di creare un indice
ordinato alfabeticamente in cui ad ogni titolo corrisponde la posizione esatta
della scheda. Il bibliotecario costatando che il metodo adottato funzionale
decide di creare un altro indice ordinato alfabeticamente per gli autori, in cui
per ogni autore si ha la posizione delle schede contenenti i dati dei libri scritti
da quell'autore. Dunque, con il metodo degli indici, il bibliotecario effettuer le
ricerche in maniera particolarmente veloce e mirata. Questo quello che
fanno i DBMS, quando utilizzano gli indici.
In altre parole gli indici sono delle tabelle speciali associate alle tabelle dati,
che vengono poi utilizzate durante le operazioni che agiscono su queste
ultime.
Contrariamente a molti linguaggi gestionali mirati al trattamento dei file, SQL
permette di creare pi indici su una stessa tabella. Tuttavia quando si crea un
indice, SQL memorizza, oltre ai dati della tabella, anche quelli dell'indice.
Quindi ogni variazione alla tabella comporta una variazione agli opportuni
puntatori alle righe della tabella e non detto che ci sia sempre
conveniente. Ad esempio se una tabella cambia spesso dati, allora la