SQL
Indice dei contenuti
Introduzione
SQL (= Structured Query Language) è un linguaggio utile a lavorare con database relazionali.
Per esempio, esso consente di:
- creare e modificare schemi di database (DDL = Data Definition Language)
- inserire, modificare e gestire dati memorizzati (DML = Data Manipulation Language)
- interrogare i dati memorizzati (DQL = Data Query Language)
Noi ci foclizzeremo sulle funzionalità DQL del linguaggio, ovvero impareremo anzitutto come ottenere delle informazioni da basi di dati pre-esistenti, attraverso le cosiddette interrogazioni SQL.
Dialetti SQL
SQL è un linguaggio utilizzatissimo per interrogazioni di basi di dati. Esistono molti software per la gestione di dati, costruiti sulla base del linguaggio SQL: i DBMS (= Data Base Management System).
Da anni esiste uno standard, il quale definisce univocamente la sintassi del linguaggio SQL. Tuttavia, ciascun DBMS ha introdotto delle modifiche nel linguaggio SQL standard, portando alla formazione di molteplici dialetti SQL. Tra le decine, eccone alcune:
- MySQL
- PostgreSQL
- Oracle SQL
- Microsoft Access
- SQLite
- …
Di fatto, noi studieremo uno di questi dialetti SQL. Come sempre, l’importante sarà capire il funzionamento intrinseco del linguaggio: eventuali piccole variazioni sintattiche possono essere memorizzate all’occorrenza.
Per studiare e fare pratica di SQL, utilizzeremo l’IDE SQLite Online, cui si può accedere da qualsiasi browser.
Se vuoi una risorsa in italiano, ecco qui delle vecchie ma valide diapositive del corso “Basi di dati 1” del Politecnico di Milano.
Funzioni aggregate
| Funzione aggregata | Risultato |
|---|---|
COUNT |
Cardinalità |
SUM |
Sommatoria |
MAX |
Massimo |
MIN |
Minimo |
AVG |
Media |
Le funzioni aggregate possono essere utilizzate solo nelle clausole
SELECTedHAVING.
Alcune osservazioni:
- la funzione aggregata
COUNTpuò avere tre diversi tipi di parametro:- nome_attributo: conta quanti sono i valori dell’attributo nome_attributo, escludendo i valori NULL
*: conta quanti sono i record selezionati dalla clausola SELECT- DISTINCT nome_attributo: conta quanti sono i distinti valori dell’attributo nome_attributo, escludendo i valori NULL
- le funzioni aggregate
SUMeAVGpossono ricevere come argomento soltanto attributi di tipo numerico. Esse ignorano i valori NULL. - la funzioni aggregate
MINeMAXpossono ricevere come argomento sia valori numerici, sia valori testuali
Query su più tabelle
Quando si effettua una query che coinvolge più tabelle, bisogna prestare attenzione al legame esistente tra di esse.
Consideriamo un semplice database costituito dalle due seguenti tabelle:
- tabella
patients:
| patient_id | province_id |
|---|---|
| 1 | QC |
| 2 | QC |
| 3 | ON |
- tabella
province_names:
| province_id | province_name |
|---|---|
| QC | Quebec |
| ON | Ontario |
Vogliamo ottenere il patient_id di coloro che vivono in Quebec.
Il primo tentativo di query potrebbe essere il seguente:
SELECT p.patient_id
FROM patients p, province_names pn
WHERE pn.province_name == "Quebec"
Il risultato di questa semplice interrogazione è:
| patient_id |
|---|
| 1 |
| 2 |
| 3 |
Il patient_id == 3, pur non corrispondendo a “Quebec”, è presente nei risultati! Come è potuto accadere questo errore?
Così: quando si effettua una query su più tabelle (oppure quando si utilizza la clausola JOIN su più tabelle), SQL si limita a calcolare il prodotto cartesiano tra quelle tabelle, ovvero produce tutte le possibili combinazioni che si possono ottenere scegliendo una riga qualsiasi della prima tabella e una riga qualsiasi della seconda tabella.
In questo prodotto cartesiano, saranno presenti numerose righe prive di senso, nelle quali, ad esempio, un paziente con province_id == ON sarà associato a una provincia con province_id == QC.
Come possiamo sbarazzarci di questi risultati privi di senso?
Semplicemente, dobbiamo ricordarci di esplicitare quali sono gli attributi che legano le tabelle, ovvero quegli attributi che devono essere uguali affinché il risultato ottenuto sia sensato.
La query precedente deve essere modificata in questo modo:
SELECT p.patient_id
FROM patients p, province_names pn
WHERE pn.province_name == "Quebec" AND p.province_id == pn.province_id
La seconda condizione, appena aggiunta nella clausola WHERE, indica il legame tra le tabelle patients e province_names, escludendo dal risultato tutte le possibili combinazioni prive di senso.
Il risultato di questa interrogazione è quello desiderato:
| patient_id |
|---|
| 1 |
| 2 |
Operatori usati nella clausola WHERE
- operatori logici:
AND,OR,NOT - gestione dei valori nulli:
IS NULL,IS NOT NULL IN. Esempio:... WHERE city IN ('Milano', 'Roma', 'Genova')BETWEEN. Esempio:... WHERE age BETWEEN 0 AND 18. I valori iniziale e finale sono inclusi nella selezione.LIKE: confronta il valore di un attributo di tipo carattere con un modello di stringa, che può contenere caratteri jolly. I caratteri jolly sono: -_(underscore): per indicare un singolo carattere qualsiasi in quella posizione della stringa -%(percent): per indicare una sequenza di caratteri di lunghezza qualsiasi in quella posizione della stringa
Per esempio: -name LIKE 'ros%': l’attributonamedeve iniziare perros, seguito da almeno un altro carattere. -name LIKE '%ati': l’attributonamedeve finire perati, preceduto da almeno un altro carattere. -name LIKE '%ros%': l’attributonamedeve contenereros, preceduto da almeno un altro carattere e seguito da almeno un altro carattere. -name LIKE '_ati': l’attributonamedeve finire perati, preceduto da un solo altro carattere (in altri termini,namedeve essere lungo 4 caratteri e terminare inati).