La parte di SQL dedicata all'interrogazione del DBMS è probabilmente la parte più importante ed utilizzata del
linguaggio.
Innanzitutto bisogna precisare che SQL esprime le dichiarazioni in modo dichiarativo, ovvero si specifica
l'obiettivo dell'interrogazione e non il modo con cui ottenerlo; in questo si contrappone ai linguaggi
di interrogazione procedurali, come l'algebra relazionale, in cui si specifica il modo in cui
l'interrogazione deve essere eseguita. Per essere eseguita l'interrogazione deve essere analizzata
dall'interprete SQL (che è un componente del DBMS) per essere tradotta in un'interrogazione
equivalente in linguaggio procedurale.
Interrogazioni semplici
Le interrogazioni in SQL sono specificate tramite l'uso dell'istruzione select la cui struttura
essenziale è la seguente :
Target list
Select ListaAttributi
Clausola from
From ListaTabelle
Clausola where
[ where Condizione ]
L'interrogazione SQL seleziona, tra le righe che appartengono al prodotto cartesiano delle tabelle elencate
nella clausola from, quelle che soddisfano la clausola where (se è assente vengono selezionate tutte le righe).
Su ciascuna riga vengono considerate quelle che compaiono nella target list (tutte se è specificato il
carattere jolly *).
Nella target list possono essere definiti degli alias, ovvero dei nomi che possono essere usati,
successivamente, per richiamare il campo.
Esempio:
Select Stipendio as Salario
from Impiegato
where Cognome = "Rossi"
Prende il valore dello stipendio di "Rossi" dalla tabella Impiegato ridefinendolo come Salario.
Nella target list possono essere inserite anche espressioni generiche (addizione, sottrazione, moltiplicazione ecc.).
Ad esempio :
Select Stipendio as Salario, Stipendio/12 as SalarioMensile
from Impiegato
where Cognome = "Rossi"
Per quanto riguarda la clausola from essa rappresenta l'insieme delle tabelle a cui si vuole accedere,
e delle quali verrà eseguito il prodotto cartesiano. Nel caso di più tabelle il join (unione)
viene eseguito specificando nella clausola where il legame tra le tabelle. Considerando l'esempio
del paragrafo precedente (tabelle Impiegato e Dipartimento) e volendo prendere valori da entrambe le tabelle:
Select Impiegato.Nome, Impiegato.Cognome, Dipartimento.Citta
From Impiegato, Dipartimento
Where Impiegato.Dipart = Dipartimento.Nome
Rispetto agli esempi precedenti si nota l'uso del punto (in piena sintassi OOP) per indicare a quali
a quale tabella si riferisce l'attributo.
La clausola where ammette una serie di espressioni booleane (=logiche); è possibile,
all'interno della clausola, combinare predicati semplici con gli operatori logici and, or e not.
Ciascun predicato semplice confronta (con gli operatori =,<>,<,>,<= e >=) una espressione costruita
a partire dai valori degli attributi per la riga o con un valore costante o con il risultato
della valutazione di un'altra espressione.
Esempio:
Select Nome
From Impiegato
Where Cognome = 'Rossi' and
(Dipart = 'Amministrazione' or Dipart = 'Produzione')
che seleziona l'impiegato di nome "Rossi" appartenente al dipartimento 'Amministrazione' o 'Produzione'.
Oltre agli operatori standard già citati SQL mette a disposizione l'operatore like per il confronto di stringhe.
Tale operatore si comporta come l'operatore di uguaglianza ma, a differenza di quest'ultimo,
supporta anche i caratteri "%" (percentuale) e "_" (trattino sottolineato). Il primo rappresenta
un carattere arbitrario mentre il secondo una stringa arbitraria (anche vuota).
Ad esempio:
Select *
From Impiegato
Where Cognome like '_o%i'
Seleziona tutti gli impiegati il cui cognome termina con la lettera "i" e la cui seconda lettera è una "o".
Di particolare importanza la gestione dei valori null nella valutazione dei predicati. Infatti nell'algebra
booleana convenzionale si prendono in considerazione unicamente due valori (vero o falso)
mentre abbiamo visto che avendo a che fare con delle basi di dati, possiamo avere anche il valore null
(=sconosciuto). Le ultime versioni di SQL gestiscono i campi null considerandoli nella valutazione
di relazioni complesse , estendendo a tre valori, vero | falso | null appunto, il possibile risultato.
Ultima precisazione riguarda la selezione dei campi null che si effettua tramite la sintassi:
Attributo is [not] null
Tale predicato risulta vero solo se il valore è null. Il predicato not null è il suo contrario.
Uso del join
L'ultima versione di SQL (SQL-2) ha introdotto una sintassi alternativa per l'espressione di join che
permette di distinguere tra le condizioni che rappresentano condizioni di join e quelle
che rappresentano condizioni di selezioni di riga. Inoltre il linguaggio è stato arricchito
di nuove espressioni di join.
Innanzitutto la sintassi è la seguente:
Select AttrExpr [ [as] Alias ] {, AttrExpr [ [as] Alias ] }
From Tabella [ [as] Alias ]
{, TipoJoin Tabella [ [as] Alias ] on CondizioneDiJoin }
[ where AltraCondizione ]
Mediante questa sintassi la condizione di join non compare come argomento della clausola where,
ma viene invece spostata nell'ambito della clausola from, associata alle tabella che vengono coinvolte nel join.
Il parametro TipoJoin specifica quale è il tipo di join da usare, ed ad esso si possono sostituire
i termini inner, right outer, left outer o full outer (in cui il qualificatore outer è opzionale).
L'operatore inner join è il più comune e produce una selezione delle righe del prodotto cartesiano
per cui la condizione è vera.
Ad esempio l'interrogazione realizza precedentemente con l'utilizzo del where ora può essere riscritta:
Select I.Nome, Cognome, Citta
From Impiegato I inner join Dipartimento D on Dipart = D.Nome
Questo è il caso di un join interno, perché le righe che vengono coinvolte nel join sono in generale
un sottoinsieme delle righe di ciascuna colonna. Può, infatti, capitare che alcune righe
non vengano considerate in quanto non esiste una corrispondente riga nell'altra non vengano
considerate in quanto non esiste una corrispondente riga nell'altra per cui la condizione
sia soddisfatta. Questo comportamento molto spesso non rispetta le esigenze delle applicazioni,
le quali, alla eliminazione delle righe operata dal join, possono preferire di mantenere le righe,
ponendo eventualmente opportuni valori null. Il join esterno (outer join) ha proprio questo compito.
Esistono tre diversi tipi di join esterno : left, right e full. Con il full join vengono presi tutti
i valori delle tabelle, con il left tutti quelli della prima tabella specificata mentre con il right
tutti quella della seconda.
Mentre una relazione è costituita da un insieme non ordinato di tuple, nell'uso reale delle basi di
dati sorge spesso il bisogno di costruire un ordine sulle righe delle tabelle. SQL permette di costituire
un ordine con l'istruzione order by posta dopo la clausola where. La sintassi è :
Order by AttrDiOrdinamento [ ASC | DESC ]
{ , AttrDiOrdinamento [ ASC | DESC ] }
In questo modo si specificano gli attributi che devono essere presi in considerazione per realizzare
l'ordinamento (crescente o decrescente).
Operatori aggregati
Tali operatori sono una serie di parole chiave del linguaggio SQL dedicate all'aggregazione dei dati,
grazie ai quali è possibile definire interrogazioni di notevoli interesse applicativo. E' necessario ricorrere
a questi operatori ogni qual volta occorra valutare delle proprietà che dipendono da insiemi di righe.
Lo standard SQL prevede cinque operatori aggregati, divisibili in due gruppi: count da una parte e sum,
max, min, avg dall'altra.
L'operatore count permette di determinare il numero di righe di una interrogazione; la sintassi è la seguente:
Count ( * | [ distinct ] | [ all ] ListaAttributi )
L'opzione * restituisce il numero delle righe; l'opzione distinct, invece, restituisce il numero dei
diversi valori degli attributi mentre l'opzione all restituisce il numero dei valori diversi da null.
Ad esempio:
Select count(distinct Stipendio)
From Impiegato
Restituisce il numero dei diversi valori dell'attributo Stipendio fra tutte le righe della tabella Impiegato.
Oppure:
Select count(all Nome, Cognome)
From Impiegato
Restituisce il numero delle righe che possiedono un valore diverso da null sia per l'attributo Nome che per
l'attributo Cognome.
Gli altri operatori di aggregazione richiedono, invece, solo un attributo o un'espressione,
eventualmente preceduta dalle parole chiave distinct o all. Le funzioni sum ed avg ammettono
come argomento solo espressione numeriche mentre max e min accettano anche intervalli di tempo e stringhe.
Gli operatori hanno il seguente significato:
· Sum : restituisce la somma dei valori posseduti dall'attributo su tutte le righe
· Max e min : restituiscono il massimo ed il minimo valore tra quelli di ciascuna riga (su questi operatori distinct o all non hanno alcun effetto)
· Avg : restituisce il valore medio tra quelli dell'attributo
Interrogazioni con raggruppamento
Qualora occorra produrre delle aggregazioni a dei sottoinsiemi di righe occorre fare ricorso alla
clausola group by. Questa istruzione permette di creare dei raggruppamenti parziali,
mostrando una sola riga per ogni insieme che ha uno stesso valore nell'attributo passato
come parametro.
Ad esempio:
Select Dipart, avg(Stipendio)
From Impiegato
Group by Dipart
Questa interrogazione ha come risultato un'insieme di righe, una per ogni valore dell'attributo Dipart,
contenente ognuna il nome del dipartimento e la media tra i valori dell'attributo Stipendio relativi
a ciascun dipartimento.
Predicati sui gruppi
Una volta eseguito un raggruppamento in sottoinsiemi con la clausola group by è possibile
selezionare solo alcuni gruppi usando la clausola Having.
La clausola having è il corrispondente per i gruppi della clausola where per gli attributi.
Essa descrive le condizioni che si devono applicare al termine dell'esecuzione di una
interrogazione che fa uso della clausola group by.
Esempio:
Select Dipart, sum(Stipendio) as SommaStipendi
From Impiegato
Group by Dipart
Having SommaStipendio>100
Volendo riassumere la sintassi SQL dell'istruzione select con tutte le clausole analizzate avremmo che:
Select ListaAttributiOEspressioni
From ListaTabelle
[ where CondizioniSemplici ]
[ group by ListaAttributiDiRaggruppamento ]
[ having CondizioniAggregate ]
[ order by ListaAttributiDiOrdinamento ]
Manipolazione dei dati in SQL
La parte di manipolazione dei dati si occupa delle operazioni di inserimento,
modifica e cancellazione delle righe.
Inserimento di righe
Il comando di inserimento di righe nella base di dati presenta due sintassi alternative:
Insert into NomeTabella [ ListaAttributi ]
< values ( ListaDiValori ) | SelectSQL >
Questa sintassi permette di inserire una riga specificandone i valori dei suoi attributi.
Una seconda sintassi, meno usata ma più consona all'impostazione SQL che ha come oggetto
le tabelle e non le singole righe, permette di aggiungere degli insiemi di righe. La sua sintassi è:
Insert into NomeTabellaDestinazione
( Select ListaAttributi
from NomeTabellaOrigine
where Condizione )
In questo modo vengono inseriti nella tabella destinazione le righe risultanti
dalla selezione sulla tabella origine.
Cancellazione delle righe
Il comando SQL delete è il comando che permette di eliminare delle righe dalle tabelle di una base di dati.
La sintassi è:
Delete from NomeTabella [ where Condizione ]
…e attua la cancellazione delle righe che rispondono alla condizione specificata.
La condizione rispetta la sintassi SQL, per cui potremmo avere al suo interno delle interrogazioni
nidificate che fanno riferimento ad altre tabelle. Un semplice esempio che elimina i dipartimenti senza impiegati:
Delete from Dipartimento
Where Nome not in (select Dipart
From Impiegato)
E' da notare la differenza tra il comando delete ed il comando drop. Ad esempio il comando:
Delete from Dipartimento
…elimina tutte le righe della tabella dipartimento, ma lo schema rimane immutato; il comando,
infatti, cancellerà solo le istanze della tabella. Mentre il comando:
Drop table Dipartimento cascade
…elimina tutte le istanze della tabella, nonché lo schema.
Modifica delle righe
In SQL la modifica delle righe avviene mediante l'utilizzo del comando update, seguendo la sintassi:
Update NomeTabella
Set Attributo = < Espressione | SelectSQL | Null | default >
{ , Set Attributo = < Espressione | SelectSQL … > }
[ where Condizione ]
Il comando update permette di aggiornare uno o più attributi delle righe di NomeTabella che soddisfano
l'eventuale condizione. Se la condizione non compare ovviamente si suppone di default il valore vero
e si esegue la modi fica su tutte le righe della tabella.
Ecco un esempio che aumenta del 20% lo stipendio degli impiegati che si chiamano "Claudio":
Update Impiegato Set Stipendio = Stipendio * 1.2
Where Nome = 'Claudio'
Lascio al lettore il compito di interpretare la seguente istruzione di update:
Update Impiegato
Set Stipendio = ( Select Max(Stipendio) from Dirigenti )
Where Nome like '_l*di_' and Residenza = 'Sestri Levante' and Domicilio = 'Milano' and DataNascita > 8-23-1975 and DataNascita < 8-25-1975
Creare un database
Per creare un database in mysql dobbiamo utilizzare la sintassi
CREATE TABLE nome_tabella(
campo1 tipo [(dimensioni)],
campo2 tipo [(dimensioni)],
PRIMARY KEY (`campoN`)
);
i tipi di campo che ci interessano sono:
"int" di tipo intero
"varchar" di tipo carattere (fino a 255)
"longtext" di tipo carattere (senza limite)