Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Il linguaggio SQL (Structured Query Language) è nato con lo scopo di poter eseguire con facilità:
• la definizione e la creazione di un database relazionale;
• le diverse operazioni di gestione dei dati, quali l’inserimento, la cancellazione e la variazione dei
record di un archivio;
• l’interrogazione del database a scopo informativo.
Il linguaggio è basato su costrutti semplici e facili da imparare. Le sue caratteristiche, infine, sono
standardizzate in modo che un utente, cambiando DBMS, non debba apprendere un nuovo
linguaggio per usare la base di dati.
Le interrogazioni che si costruiscono con SQL sono un’estensione di quelle che si realizzano con
sequenze di operazioni relazionali, in quanto con SQL è possibile, come nelle query di Access,
effettuare calcoli, raggruppamenti e ordinamenti.
Come abbiamo visto nel precedente capitolo, Access permette di costruire una query in modalità
QBE e di visualizzarne il corrispondente codice SQL. È anche possibile costruire l’interrogazione
in SQL e, passando alla Visualizzazione Struttura, esaminare la versione QBE della query. Per
imparare il linguaggio è molto utile passare da una modalità all’altra e osservare come una frase
di SQL viene rappresentata in QBE oppure come una query QBE, di cui si conoscono gli effetti,
viene tradotta in SQL.
N Comprendere 1
Impiegato Dipartimento
Coordinare mette in re- 1 Coordinare N
lazione un dipartimento ID {PK} Codice {PK}
con il dipendente che lo Nome Descrizione
dirige. È un’associazione Cognome Sede
uno a molti perché un Residenza Partecipazione
dipendente può essere a Stipendio facoltativa di Impiegato
capo di più di un diparti- in quanto solo alcuni Lettura del modello
mento, mentre un dipar- dipendenti sono Ogni impiegato può coordinare uno
timento ha un solo ma- manager. o più dipartimenti; ogni dipartimen-
nager. to deve essere coordinato da un solo
impiegato.
Il passaggio dal modello concettuale al modello relazionale porta al seguente schema di database
dove, come al solito, gli attributi sottolineati rappresentano le chiavi primarie, mentre le chiavi
esterne sono indicate in corsivo.
Nella seguente figura sono mostrate le tabelle Impiegati e Dipartimenti con alcuni dati di esempio.
• Definire il database, la struttura delle tabelle che lo compongono, gli indici, le associazioni tra
le tabelle e le viste logiche. Un elenco di comandi SQL che assolvono a funzioni di Data
Definition Language (DDL) è presentato nel Paragrafo 4.
• Modificare i dati contenuti nel database, con le operazioni di inserimento, variazione e cancel-
lazione, ed effettuare le interrogazioni. I comandi Insert, Update, Delete e Select, che apparten-
gono al Data Manipulation Language (DML) di SQL, sono discussi nei Paragrafi 5 e 6.
• Definire gli utenti e controllare gli accessi al database. I comandi Grant e Revoke, che apparten-
gono alle funzioni di Data Control Language (DCL) di SQL, sono presentati nel Paragrafo 13.
• Gestire e controllare le transazioni con un sottoinsieme del linguaggio che prende il nome di
Transaction Control Language (TCL). I comandi Commit e Rollback, che sono stati introdotti
nel Capitolo 1, saranno approfonditi nel Capitolo 6, con esempi relativi al software MySQL.
Il linguaggio SQL fornisce inoltre gli opportuni comandi per definire in modo facile i tabulati di
uscita dei risultati (report), per recuperare i dati quando accade un’interruzione del programma,
un guasto nei supporti magnetici o un malfunzionamento del sistema, per definire le viste degli
utenti sul database, per garantire la sicurezza dei dati nei confronti degli accessi di più utenti.
Per i dati numerici la precisione p indica il numero massimo di cifre che il numero può contenere,
esclusi il segno e il punto decimale.
Per i numeri decimali il valore s indica il numero di cifre che seguono il punto decimale.
I dati numerici floating point sono memorizzati in forma esponenziale; la precisione riguarda solo
le cifre della mantissa e indica il numero di cifre significative del dato.
La parola NUMERIC può essere usata al posto di DECIMAL.
La parola CHARACTER è equivalente a CHARACTER(1), e può essere abbreviata con CHAR.
DECIMAL è equivalente a DECIMAL(15,0).
Altre abbreviazioni sono:
• CHAR(n) invece di CHARACTER(n);
• INT(p) invece di INTEGER(p);
• DEC(p,s) invece di DECIMAL(p,s).
ESEMPIO 1
Creazione delle tabelle Impiegati e Dipartimenti.
ID è chiave primaria Campi obbligatori: non
della tabella. sono ammessi valori nulli
in Nome e Cognome.
CREATE TABLE Impiegati(
ID smallint primary key, Il valore da attribuire a
Nome char(20) not null, Residenza in caso di
Cognome char(30) not null, valore nullo.
Residenza char(20) default '*** Manca Residenza',
Stipendio decimal(9,2),
Dipartimento char(5) references Dipartimenti(Codice),
UNIQUE(Cognome, Nome, Dipartimento)
);
La struttura di una tabella può essere modificata in un secondo tempo con il comando ALTER
TABLE, per aggiungere una nuova colonna (ADD) a quelle già esistenti, oppure per togliere
una colonna (DROP).
Esempio
Inserisce in Impiegati una nuova colonna di nome
ALTER TABLE Impiegati
Nascita per registrare la data di nascita del dipendente.
ADD Nascita date;
Esempio
Crea l’indice IndiceImpiegati sui campi Cognome e
CREATE UNIQUE INDEX IndiceImpiegati Nome di Impiegati: non ci possono essere dipendenti
ON Impiegati(Cognome, Nome); con lo stesso cognome e lo steso nome.
I comandi illustrati rappresentano la parte del linguaggio SQL che fa riferimento alla catego-
ria dei comandi definiti con la sigla DDL (Data Definition Language), cioè il linguaggio che
consente di implementare il modello logico dei dati sulle memorie di massa del computer.
Occorre osservare che nelle versioni moderne dei prodotti DBMS le operazioni di creazione di
tabelle e di indici, oltre che di modifica alla struttura della tabella o di cancellazione di tabelle
e indici, vengono effettuate, come in Access, attraverso un’interfaccia interattiva che facilita il
lavoro dell’utente, il quale può anche non conoscere la sintassi dei comandi sopra illustrati.
ESEMPIO 2
Eseguire operazioni di manipolazione sulla tabella Impiegati.
UPDATE Impiegati
SET Dipartimento = 'Prod' Assegnamento del dipendente con
WHERE ID = 20; ID=20 al dipartimento Produzione.
UPDATE Impiegati
SET Stipendio = Stipendio * 1.05 Aumenta del 5% lo stipendio ai dipendenti
WHERE Dipartimento = 'Prod'; del dipartimento Produzione.
Come già detto a proposito della creazione delle tabelle, nell’uso pratico del linguaggio, le
operazioni di inserimento, così come quelle di modifica e di cancellazione, vengono facilitate
mediante l’uso di maschere video che guidano l’utente nelle operazioni di trattamento dei dati,
all’interno di un ambiente software basato sull’uso di interfacce grafiche amichevoli.
Si pensi, nel caso di Access, all’uso delle maschere e alla possibilità di manipolare dati agendo
direttamente sulla Visualizzazione Foglio dati di una tabella.
Quindi i comandi di tipo DML (Data Manipulation Language) del linguaggio SQL rimangono
nascosti all’utente che può effettuare le operazioni di manipolazione senza conoscere la sintassi
delle istruzioni.
WHERE Condizioni ; Una espressione logica che specifica quali righe considerare. Espressione
booleana ottenuta componendo confronti con gli operatori AND OR e NOT.
SELECT *
FROM Impiegati
WHERE Residenza = 'Roma';
Il comando Select possiede i due predicati ALL e DISTINCT. Con il predicato ALL si richiede che
nel risultato dell’interrogazione siano incluse tutte le righe, anche se duplicate, che soddisfano
alle condizioni contenute nel comando. Questo predicato è di default ed in genere è omesso.
Se viene specificato il predicato DISTINCT le righe duplicate nella tabella risultante sono ridotte
a una. Per esempio, se si desidera ottenere l’elenco di tutte le località di residenza dei dipendenti,
senza duplicati, si deve usare la clausola DISTINCT prima dell’indicazione dell’attributo.
Come si è anticipato nel Capitolo 3, i DBMS commerciali, per ragioni di efficienza, non rispettano
strettamente il modello relazionale, che non ammette la presenza di righe duplicate in una
tabella. Il predicato DISTINCT fa in modo che un comando Select produca una tabella coerente
con tale modello.
SELECT ID AS Matricola, Nome, Cognome Elenco degli impiegati con ID, Nome
FROM Impiegati; e Cognome, ma usando Matricola
come intestazione della colonna ID.
Con il comando SELECT si può richiedere il calcolo di espressioni basate sugli attributi della
tabella; la tabella risultante contiene delle colonne con i risultati del calcolo per ogni riga. Tali
colonne possono avere un’intestazione opportuna utilizzando la parola AS. In assenza di AS
l’intestazione della colonna con l’espressione viene costruita dal sistema in modo differente a
seconda dell’implementazione. Nel caso di Access il nome è Espr1 per la prima espressione, Espr2
per la seconda espressione e così via.
Si osservi che per controllare la presenza di valori nulli si deve usare il predicato IS NULL, mentre
è errato ricercare tali valori in altro modo, come è mostrato di seguito. Si ricorda, a proposito, che
il dipendente con ID=5 non è assegnato ad alcun dipartimento.
Per scrivere un’interrogazione in SQL nell’ambiente di Access, bisogna creare una nuova query
accedendo alla Visualizzazione Struttura, e chiudere la finestra di dialogo Mostra tabella senza
scegliere alcuna tabella. Poi si deve fare clic sulla scelta che è diventata la proposta del pulsante
Visualizza.
Le istruzioni del linguaggio SQL sono a formato libero e terminano con il carattere punto e
virgola: un comando SQL può essere scritto liberamente su una o più righe e le parole chiave del
linguaggio possono essere scritte indifferentemente a caratteri maiuscoli o minuscoli.
In un comando SQL possono comparire commenti, con la convenzione che si considera un
commento tutto quello che compare in una riga di seguito alla sequenza di caratteri “-- “.
Per esempio, i due comandi SELECT mostrati di seguito sono entrambi corretti e sono
sintatticamente identici; sono stati anche inseriti: un commento che occupa parte di una riga e
tre commenti che occupano un’intera riga.
• La selezione, che estrae da una relazione solo le righe che soddisfano a una certa condizione,
viene realizzata nel linguaggio SQL specificando la condizione di selezione nella clausola Where
del comando Select.
Esempio
• L’operazione di proiezione, che permette di ottenere una relazione contenente solo alcuni
attributi della relazione di partenza, si realizza scrivendo l’elenco degli attributi richiesti dopo
la parole Select.
Esempio
SELECT *
Per maggiore chiarezza, o se ci
FROM Impiegati, Dipartimenti sono attributi con il medesimo nome
WHERE Impiegati.Dipartimento = Dipartimenti.Codice; nelle due tabelle, si usa la dot
notation, specificando oltre al nome
dell’attributo anche quello della
Condizione di uguaglianza tra attributi:
tabella alla quale appartengono.
esempio di equi-join. Sono combinate solo
le righe che soddisfano alla condizione.
Nella versione di SQL adottata da Access il join viene indicato, in accordo con la terminologia
introdotta nel Capitolo 3, come inner join. Se la precedente interrogazione viene realizzata con
Access in modalità QBE e, successivamente, si accede alla query in visualizzazione SQL, si legge
(una volta ripulito dalle parentesi inutili) il seguente comando:
La sintassi adottata da Access è una delle sintassi ammesse fra gli standard di SQL2, mentre il
modo di costruire le congiunzioni presentato all’inizio del paragrafo è quello dello standard di
base del linguaggio.
Va precisato che Access (come tutti gli SQL che ammettono tale ultima sintassi) accetta ed esegue
correttamente le interrogazioni costruite secondo lo standard di base. Naturalmente, quando il
comando Select è costruito direttamente da Access partendo da una QBE, l’interrogazione è
realizzata secondo gli standard tipici dell’implementazione.
Come si è anticipato nel Capitolo 3, gli strumenti per recuperare le informazioni sulle righe che
non hanno corrispondenti nella congiunzione sono i join esterni e, in particolare, il left join che
è presentato a fine paragrafo.
• Interrogazioni in SQL
Dopo aver visto come si rappresentano nel linguaggio SQL le operazioni fondamentali del
modello relazionale, impariamo a costruire interrogazioni composte da una sequenza di opera-
zioni relazionali.
Esempio
Per ottenere l’elenco dei dipendenti che lavorano in un dipartimento con sede a Roma, con
cognome, nome e descrizione del dipartimento, occorre dapprima operare una selezione su
Dipartimenti per Sede = ‘Roma’; poi si deve effettuare una congiunzione della tabella ottenuta
con la tabella Impiegati e, infine, applicare una proiezione sugli attributi Cognome, Nome, Descri-
zione sulla nuova tabella risultante.
Per semplificare la scrittura del comando Select è possibile fare ricorso agli alias per il nome della
tabella, specificando dopo il nome originale della tabella la parola AS seguita dal nuovo nome.
Risulta evidente la maggior chiarezza dell’ultima interrogazione rispetto alle precedenti: la sin-
tassi adottata da Access ha il pregio di separare nettamente la condizione di congiunzione, che
viene espressa nella parte From dell’interrogazione, dalle condizioni di selezione, che sono
espresse nella parte Where della query.
Per sopperire alla minor chiarezza delle interrogazioni scritte nella versione base di SQL è
opportuno scrivere la parte Where dell’interrogazione su più righe, come nell’esempio preceden-
te, riportando prima le condizioni per la congiunzione delle tabelle e poi le condizioni che
esprimono la selezione.
Dagli esempi precedenti si può osservare come nel linguaggio SQL con poche parole di codice
sia possibile estrarre da una base di dati tutte le informazioni che si desiderano. Le stesse
operazioni, formulate attraverso le istruzioni di un linguaggio di programmazione tradizionale,
richiederebbero un elevato numero di righe di codice, oltre che lunghi processi di ricerca sui file
e di confronti tra i campi dei record.
• Il self-join si attua quando si congiunge una tabella con se stessa. Come si è osservato nel
Capitolo 3, questa esigenza si presenta nel caso delle associazioni ricorsive, per esempio nel caso
di una gerarchia aziendale o della distinta base che descrive oggetti composti da diverse parti.
Esempio
Mostriamo come si possa realizzare un self-join su una tabella. Si consideri l’associazione
esistente tra l’entità Oggetto di attributi: ID, Descrizione e Qta, e le sue parti (che sono altri
oggetti). La tabella che rappresenta gli oggetti e tale associazione ha lo schema sotto riportato
assieme a un’istanza della tabella Oggetti.
AS Parti AS Composto
L’interrogazione SQL che elenca le parti che compongono la camicia è mostrata in figura assieme
alla tabella visualizzata al momento dell’esecuzione della query.
• I join esterni: oltre ai join interni il linguaggio SQL permette di costruire dei join che includono
nella congiunzione anche quelle righe di una delle due tabelle che non hanno corrispondenti
nell’altra. Si tratta dei join esterni e, come si è già detto, corrispondono alle operazioni di left
join, right join, full join dell’algebra relazionale.
Tra i join esterni consideriamo il left join e mostriamo la sua utilità nella soluzione di un tipico
problema di assenza: elencare i dipartimenti che non hanno dipendenti loro assegnati. Per farlo
congiungiamo la tabella Dipartimenti e la tabella Impiegati con un left join.
SELECT Descrizione
FROM Dipartimenti D LEFT JOIN Impiegati I ON
D.Codice = I.Dipartimento
I dipartimenti senza impiegati si riconoscono per la
WHERE Cognome IS NULL;
presenza di valori nulli nei campi che provengono da
Impiegati. Per il controllo si usa il predicato IS NULL.
• Funzione COUNT
La funzione COUNT conta il numero di occorrenze selezionate dall’interrogazione. La sintassi del
linguaggio SQL richiede di specificare come argomento della funzione il nome di un attributo
oppure il carattere * (asterisco). Nel primo caso sono conteggiati i valori non nulli nella colonna
considerata; nel secondo caso, la funzione Count(*) calcola il numero di righe nella tabella.
SELECT COUNT(*)
Conta il numero dei dipendenti residenti a Roma.
FROM Impiegati Restituisce 2.
WHERE Residenza = 'Roma';
• Funzione SUM
La funzione SUM restituisce la somma dei valori contenuti in una colonna, specificata come
argomento della funzione: naturalmente l’attributo utilizzato nel calcolo deve essere di tipo
numerico; i valori nulli sono trascurati dalla funzione Sum.
• Funzione AVG
La funzione AVG (dall’inglese average = media), calcola la media dei valori (numerici) contenuti
in una colonna di una tabella. L’argomento della funzione può essere un’espressione aritmetica
anziché il nome di un attributo. La media calcolata dalla funzione Avg è la media aritmetica, cioè
la somma dei valori diviso il numero dei valori. La funzione Avg non include nel calcolo i valori
Null presenti nella colonna.
SELECT AVG(Stipendio)
Calcola lo stipendio medio dei
FROM Impiegati, Dipartimenti
dipendenti che lavorano a Torino.
WHERE Dipartimento = Codice AND Restituisce 46916,67.
Sede = 'Torino';
SELECT MIN(Stipendio),
Calcola lo stipendio minimo e massimo dei dipendenti.
MAX(Stipendio)
Restituisce 25000 e 85000.
FROM Impiegati;
SELECT MIN(Cognome),
Primo e ultimo cognome (secondo l’ordine alfabetico) dei dipendenti.
MAX(Cognome) Restituisce Bianco e Volpi.
FROM Impiegati;
9 Ordinamenti e raggruppamenti
Nel comando Select si può inserire la clausola ORDER BY per ottenere i risultati di un’interroga-
zione ordinati secondo i valori contenuti in una o più colonne, che vengono specificate di seguito
alla clausola Order By. L’indicazione delle colonne da considerare nell’ordinamento avviene pre-
cisando il nome della colonna oppure la posizione che essa occupa nella lista che segue la parola
Select: 1 per la prima posizione, 2 per la seconda, e così via.
L’ordinamento può essere crescente (le stringhe dalla A alla Z e i numeri dal minore al maggiore)
oppure decrescente (le stringhe dalla Z alla A e i numeri dal maggiore al minore): i due tipi di
ordinamento sono precisati usando le parole chiave ASC per crescente e DESC per decrescente.
L’ordinamento è crescente per default e quindi va specificata la parola Desc solo se si desidera
l’ordinamento decrescente.
Esempio
Si consideri una tabella di fatture che contiene, per ogni fattura, la descrizione del prodotto, il
suo prezzo unitario e la quantità ordinata.
SELECT Dipartimento,
COUNT(ID) AS Dipendenti,
Elenco dei dipartimenti con la somma degli
SUM(Stipendio) AS Stipendi
stupendi e il numero di addetti per dipartimento.
FROM Impiegati
GROUP BY Dipartimento;
1
Le righe sono
raggruppate per
dipartimento.
2
Le funzioni di aggrega-
zione sono applicate
separatamente ai singoli
raggruppamenti.
Se nell’elenco si desidera che compaia, invece del codice, il nome per esteso del dipartimento,
bisogna effettuare il raggruppamento sul campo Descrizione della tabella Dipartimenti.
SELECT Descrizione,
COUNT(*) AS Dipendenti, Nell’elenco sono esclusi i dipendenti
che non sono inquadrati in alcun
SUM(Stipendio) AS Stipendi
dipartimento (come il dipendente
FROM Impiegati, Dipartimenti
con ID =5 dell’esempio) che
WHERE Impiegati.Dipartimento = Dipartimenti.Codice
scompaiono nella congiunzione.
GROUP BY Descrizione;
Se l’istruzione Select contiene la clausola Where, i valori vengono raggruppati dopo aver
operato la selezione sulle righe che rispettano le condizioni scritte accanto a Where.
Selezionare Dove
Le condizioni scritte nella nel menu a discesa
3
riga Criteri della QBE Le condizioni scritte nella riga della riga Formula.
sono interpretate come Criteri della QBE sono 1
condizioni sui raggruppa- interpretate come condizioni
menti: clausola Having. sulle righe: clausola Where.
Sintetizziamo in un unico quadro le diverse clausole che possono apparire nel comando Select: