L istruzione SELECT di SQL Sintassi dell istruzione SELECT... 2 Clausola WHERE... 3 Clausola ORDER BY... 5 Le funzioni di aggregazione... 6 Raggruppamenti... 9 Inner Join (giunzione naturale o join interno)...10 1
Sintassi dell istruzione SELECT Sicuramente la prima e la più utilizzata tra le istruzioni del linguaggio SQL. Serve letteralmente a selezionare un gruppo di valori da un insieme di tabelle, specificando opzionalmente dei criteri di selezione, di raggruppamento e di ordinamento. La sintassi generale dell'istruzione è: SELECT <campi> FROM <origini> [ WHERE <criteri> ] [ GROUP BY <campi> ] [ HAVING <criteri> ] [ ORDER BY <criteri di ordinamento> ] Delle sei righe indicate soltanto le prime due sono obbligatorie; le successive rappresentano ulteriori clausole oppure operatori SQL che vedremo in seguito. Nella sua forma più semplice si compone del nome dei campi da scegliere e dal nome di una tabella come origine: SELECT id, nome, cognome FROM dipendenti; L'esempio estrae i campi id, nome e cognome dalla tabella di nome dipendenti; nessun filtro sarà operato ma saranno quindi restituite tutte le righe presenti all'interno della tabella indicata. Se dovesse essere necessario estrarre tutti i campi dall'origine indicata può essere utilizzato il simbolo * come segue: SELECT * FROM dipendenti; I dati saranno restituiti in forma tabellare (quindi a righe e colonne) ed i nomi dei campi saranno quelli originali recuperati dalla tabella di origine. In caso di necessità sarà possibile modificare il nome dei singoli campi restituiti utilizzando l'operatore AS: SELECT id AS id_cliente, nome AS nome_cliente, cognome AS cognome_cliente FROM clienti; La riga precedente estrae i tre campi id, nome e cognome e li assegna ai campi di nome id_cliente, nome_cliente e cognome_cliente. Sebbene sia possibile inserire degli spazi nei nomi dei campi si consiglia di evitarlo sia per diminuire la probabilità di errori sia perché non tutti i database lo consentono. Esistono due sintassi molto comuni per racchiudere i nomi dei campi quando questi contengono degli spazi o altri simboli che potrebbero arrecare disturbo all'elaborazione. I due simboli sono le parentesi quadre [ ] ed il carattere di accento `. Quando un campo può riferirsi a più di una tabella dell'origine (vedremo subito dopo come specificare più di un'origine), è necessario fornire il nome dell'origine cui il campo si riferisce, ma è comunque possibile farlo anche quando si tratta di una sola origine: SELECT dipendenti.id, dipendenti.nome, dipendenti.cognome FROM dipendenti; Tutte le espressioni che abbiamo visto finora riportavano i campi di tutti i record di una sola tabella nell'ordine casuale con cui le righe vengono estratte. Utilizzando la clausola WHERE che vedremo in seguito è possibile filtrare la scelta dei record da estrarre. La clausola ORDER BY invece consente di ordinare i risultati. 2
Abbiamo lasciato per ultimo un operatore particolare utilizzabile nelle istruzioni di selezione: si tratta di DISTINCT, dedicato a filtrare le righe ripetute. La sua sintassi è molto semplice: SELECT DISTINCT <campi> FROM <origini>; Essendo posto prima dei campi, la sua azione è valida su tutti i campi; saranno infatti eliminate le righe dei risultati completamente uguali tra loro. Vediamo un esempio per semplificare la comprensione del problema: SELECT DISTINCT nome FROM dipendenti; Restituirà tutti i nominativi unici dei dipendenti; saranno ovvero esclusi i nomi duplicati. Dipendenti con nome uguale e cognome differente saranno comunque annoverati nell'unica riga con il loro nome. SELECT DISTINCT nome, cognome FROM dipendenti; Tuttavia in questo caso, se due dipendenti avessero lo stesso nome, sarebbero comunque riportati entrambi perché l'esclusione dei duplicati agisce soltanto sulle righe intere dei risultati e non sui dati da recuperare dall'origine. Sarebbero allora esclusi soltanto quei dipendenti con lo stesso nome e lo stesso cognome, caso assai difficile in una singola azienda. Clausola WHERE Sebbene si tratti di una clausola anziché di un'istruzione ed essendo utilizzata da quasi tutte le altre istruzioni si è preferito trattarla a parte. La sua unica finalità è quella di limitare le selezioni ed includere solo le righe che corrispondono ai criteri specificati. Il suo utilizzo generale è: WHERE <campo> <predicato> <valori> Campo naturalmente si riferisce al nome di un campo presente in una delle origini, predicato si riferisce ai simboli che stabiliscono una regola ai valori specificati di seguito. Il predicato si riferisce al contenuto del campo e può essere uno dei seguenti: = è uguale al valore < è minore del valore > è maggiore del valore <= è minore oppure uguale al valore >= è maggiore oppure uguale al valore <> è differente dal valore LIKE è similare al valore NOT LIKE non è similare al valore BETWEEN è compreso tra i due valori specificato a seguito NOT BETWEEN non è compreso tra i due valori IS NULL è il valore NULL IS NOT NULL non è il valore NULL IN corrisponde ad uno dei valori specificati a seguito NOT IN non corrisponde ad alcuno dei valori specificati a seguito Prima di vedere il suo utilizzo è necessario chiarire tre semplici concetti: 3
1. I campi numerici vanno testati con valori numerici come 1, 2, 3 o 40000. 2. I campi di testo vanno verificati con valori di testo, quindi stringhe racchiuse dal carattere di apostrofo come 'pippo', 'ciccio' o 'casa mia'. La regola comune stabilisce che le ricerche su campi di testo sono effettuate ignorando le differenze tra maiuscolo e minuscolo (case insensitive). 3. Gli altri tipi di campo (data, caratteri unicode, o altro genere) vanno verificati con i simboli decisi dal singolo driver del database. L'utilizzo dell'operatore WHERE è relativamente semplice: SELECT nome, cognome FROM dipendenti WHERE id > 2; Restituirà due campi di quelle righe in cui il campo ID contiene un valore superiore a 2. Come si nota, il campo specificato nell'operatore WHERE non deve necessariamente essere presente nell'elenco dei campi restituiti. SELECT nome, cognome FROM dipendenti WHERE id BETWEEN 2 AND 4; Restituirà i due campi di quelle righe in cui il campo ID contiene un valore compreso tra 2 e 4. SELECT nome, cognome FROM dipendenti WHERE ruolo LIKE 'direttore%'; Restituirà quelle righe in cui il valore del campo RUOLO inizia per DIRETTORE. Il carattere di percentuale % corrisponde al carattere jolly standard che indica qualsiasi corrispondenza al suo posto. Il carattere % può essere utilizzato soltanto come prefisso o come suffisso o entrambe le cose; non va invece utilizzato al centro di una frase: Alcune versioni del driver per il database Access utilizzano i caratteri jolly standard del DOS, cioè * al posto di % per indicare una combinazione composta da qualsiasi carattere. Abbiamo sinora visto solo selezioni formate da un'unica condizione di vincolo ma naturalmente è possibile combinare più condizioni utilizzando gli appositi operatori booleani: AND OR Specifica che il criterio precedente e quello successivo debbano restituire risultato Vero Specifica che almeno uno dei due criteri debba restituire risultato Vero Altresì ogni condizione può essere invertita utilizzando l'operatore NOT. Vediamone il funzionamento pratico: SELECT * FROM dipendenti WHERE nome='francesco' AND ruolo='direttore'; Restituirà tutti i campi della tabella dipendenti in cui il nome dell'impiegato è Francesco ed il suo ruolo è direttore. Sono esclusi tutti gli altri Francesco, tutti gli altri direttori e tutti quei dipendenti che presentano nome o ruolo differenti. SELECT * FROM dipendenti WHERE id=0 OR id > 10; Restituirà tutti i campi della tabella dipendenti in cui il campo ID contiene valore 0 oppure un valore superiore a 10. Sono quindi esclusi tutti quelli che vanno da 1 a 9 (supposto naturalmente che ID sia un campo intero). Complicando un attimo le cose otteniamo: 4
SELECT * FROM dipendenti WHERE id=0 OR id=1 OR id > 10; Restituirà tutte le righe in cui il campo ID sia uguale a 0 oppure a 1 oppure sia maggiore di 10. Nel caso in cui appaiano i due operatori AND e OR nella stessa condizione, l'operatore AND avrà la precedenza su OR. È possibile estrarre le righe in cui un determinato campo sia NULL usando l'operatore IS NULL come mostrato: SELECT * FROM dipendenti WHERE id IS NULL; Restituirà soltanto quelle righe in cui il campo ID sia Null. Viceversa: SELECT * FROM dipendenti WHERE id IS NOT NULL; Riporterà tutte quelle righe in cui ID non sia Null. Abbiamo già detto che alcuni database supportano anche il predicato IN ed il suo contrario NOT IN; questi possono essere usati in due maniere: SELECT * FROM dipendenti WHERE id IN (1, 3, 5, 7, 9); Interrogazione restituirà tutte quelle righe in cui il campo ID contiene i valori 1 o 3 o 5 o 7 o 9. Corrisponde esattamente a: SELECT * FROM dipendenti WHERE id=1 OR id=3 OR id=5 OR id=7 OR id=9; Clausola ORDER BY Uno tra i più semplici operatori del linguaggio SQL, ORDER BY consente di ordinare i risultati secondo certi criteri. La sua sintassi generale è: ORDER BY <campo> [ ASC DESC ] Si applica generalmente alle selezioni, per ottenere un elenco di righe già ordinato per ciascuno dei campi indicati. L'ordinamento è possibile sia in maniera ascendente (ASC), cioè dalla A alla Z, che rappresenta il valore di default, se omesso, che in maniera discendente (DESC) che rappresenta l'ordine contrario, cioè da Z verso A. L'ordine dei numeri rispetto i caratteri alfabetici dipende dall'implementazione del singolo driver; solitamente su ambiente Windows i numeri vengono prima delle lettere. L'utilizzo dell'operatore ORDER BY è molto semplice: SELECT * FROM dipendenti ORDER BY id; Ordinerà le righe restituite in ordine crescente (ascendente) del campo ID. SELECT nome, cognome FROM dipendenti ORDER BY nome; Tutti i nomi saranno ordinati in maniera ascendente, mentre i cognomi saranno lasciati nel loro ordine casuale. È possibile ordinare i risultati anche per più campi, al fine di ottenere un insieme di righe correttamente ordinato. 5
SELECT nome, cognome FROM dipendenti ORDER BY nome, cognome; I valori Null nell'ordinamento sono considerati come il valore più basso, cioè in caso di ordinamento ascendente sono presentati per primi, mentre in caso di ordinamento discendente sono ordinati per ultimi. Le funzioni di aggregazione Il termine funzione di aggregazione indica quelle funzioni che elaborano un insieme di righe ma restituiscono sempre un risultato; esempi di queste funzioni sono quelle che effettuano la somma dei valori di un campo, il conteggio di righe di un certo tipo, il valore massimo presente nelle righe recuperate. Il loro risultato è sempre uno, indipendentemente dal numero di righe prese in esame. Un'eccezione a questa regola è dettata dall'uso della clausola GROUP BY, che vedremo in seguito per effettuare delle spaccature ed elaborare l'aggregazione sui singoli gruppi. Sebbene ciascun database possegga le proprie funzioni di aggregazione, ve ne sono alcune così comuni da poter essere considerate ormai uno standard, ed una deficienza per un database che non le supporta. Osserviamo la sintassi generale: <funzione> (<predicato> <campo> ) Esse si applicano all'istruzione SELECT e possono apparire nell'elenco dei campi da mostrare (è così nella maggior parte dei casi) oppure nelle clausole ORDER BY ed HAVING che vedremo in seguito. Essendo inoltre funzioni e non campi, non possiedono un nome di campo reale, quindi solitamente i risultati vengono rinominati con l'operatore AS trattato nelle lezioni precedenti. Prima di vedere le funzioni più comuni in esame presentiamo un esempio generale: SELECT <funzione> (<campo>) AS <nome> FROM <tabella> WHERE <criteri>; Questa istruzione effettuerebbe il calcolo della funzione, applicata sul campo indicato, per la tabella specificata e per le righe incluse nei criteri; il risultato della funzione sarebbe infine presentato in un campo con il nuovo nome indicato a seguito dell'operatore AS. La definizione precedente a quest'ultima includeva anche un predicato, posto immediatamente prima del campo per cui effettuare il calcolo. Tale predicato può essere: ALL (Valore predefinito se omesso) Indica di prendere tutte le righe in esame estratte dalla condizione WHERE DISTINCT Indica di escludere le righe con valori del campo specificato ripetuti e quindi prenderà in esame sempre e soltanto una riga. Esistono cinque funzioni standard di aggregazione, dall'uso molto semplice e, come già detto, presenti in quasi tutti i database. La prima di queste funzioni è sicuramente COUNT, che effettua il conteggio delle righe estratte e subito vediamo un esempio molto elementare: SELECT COUNT(nome) AS conteggio FROM dipendenti; Restituisce il numero di righe con valori non NULL nella colonna nome presenti all'interno dell'intera tabella dipendenti senza applicare altre esclusioni. La funzione opererà sul campo nome e 6
quindi conterà quanti nomi sono presenti all'interno della tabella dipendenti; i valori Null saranno esclusi. Otterremmo lo stesso risultato con la seguente istruzione: SELECT COUNT(ALL nome) AS conteggio FROM dipendenti; Ciò in quanto il predicato ALL è il predefinito nel caso venisse omesso. Otterremmo invece un risultato differente con questa istruzione: SELECT COUNT(DISTINCT nome) AS conteggio FROM dipendenti; Questa restituirà il numero di nomi differenti all'interno della tabella dipendenti, escludendo infatti quelle righe con il valore nel campo nome ripetuto. Come nel caso precedente sono escluse le righe con valore NULL nel campo nome. Per includere invece tutte le righe, senza escludere né quelle con valore Null né quelle duplicate è possibile specificare il simbolo * al posto del nome del campo ed omettere il predicato ALL o DISTINCT. SELECT COUNT(*) AS conteggio FROM dipendenti; Questa istruzione semplicemente restituisce il numero di righe presenti all'interno della tabella dipendenti. Se avessimo specificato uno dei due predicati, l'istruzione avrebbe riportato un errore. Se si utilizza il simbolo * i predicati non sono necessari; viceversa utilizzando il nome di una colonna può essere utilizzato uno dei due predicati; in assenza di specifica sarà utilizzato il predicato ALL. Prima di procedere oltre vediamo altri due esempi: SELECT COUNT(nome) AS conteggio FROM dipendenti WHERE ruolo='direttore'; Restituirà il conteggio dei direttori presenti nell'elenco dei dipendenti; saranno escluse quelle righe in cui il campo nome contiene valore NULL, oltre che naturalmente tutte quelle che non corrispondono al ruolo di direttore. Inoltre le funzioni di aggregazione, come tutti gli altri valori d'altronde, possono essere affiancate da altre funzioni di aggregazione: SELECT COUNT(*) AS totale, COUNT(nome) AS nomi, COUNT(DISTINCT nome) AS nomi_unici FROM dipendenti WHERE ruolo='direttore'; Restituirà una riga composta da tre campi: 1. totale conterrà il numero complessivo di righe della tabella dipendenti in cui il ruolo sia Direttore; 2. nomi conterrà il numero di nomi dei dipendenti, escludendo i valori Null e quelli che non corrispondono a Direttore; 3. nomi_unici conterrà invece il numero di nomi univoci, contanto solo una volta quelli duplicati, escludendo quelli (anzi quella, vista l'esclusione dei duplicati) con valori Null e ruolo non corrispondente a Direttore. Un'altra funzione di aggregazione molto comune è SUM che, come dice il nome, riporta la somma dei valori presi in esame; come per tutte le altre funzioni di aggregazione il procedimento è sempre 7
lo stesso, utilizzando il nome di un campo e un predicato ALL o DISTINCT. A differenza della precedente funzione, questa e le successive non consentono di specificare l'asterisco per indicare tutti i valori del criterio e pertanto i valori Null sono sempre esclusi. Vediamo qualche esempio di funzionamento: SELECT SUM(stipendio) AS somma FROM dipendenti WHERE ruolo='impiegati'; Riporterà la somma dei dati presenti nella colonna stipendio della tabella dipendenti in cui il ruolo corrisponde a Impiegati. Sono esclusi tutti i valori NULL. Questa funzione lavorerà soltanto su valori numerici interi o decimali e restituirà errore in caso di dati di tipo carattere. Molto similare alla precedente è la funzione AVG, utilizzata per calcolare il valore medio di un campo; opera soltanto su valori numerici ed il suo funzionamento è molto semplice: SELECT AVG(stipendio) AS media FROM dipendenti WHERE ruolo='impiegati'; Restituirà lo stipendio medio di tutti gli impiegati presenti nella tabella dipendenti. Non avendo specificato il predicato sarà assunto il valore predefinito ALL che include tutte le righe nel calcolo. Specificando invece il predicato DISTINCT otterremo un calcolo differente: SELECT AVG(DISTINCT stipendio) AS media FROM dipendenti WHERE ruolo='impiegati'; Sarà infatti riportato il valore dello stipendio medio per mansione degli impiegati; cercherò di essere più chiaro: se la tabella dipendenti contenesse 10 impiegati pagati 1000 e 3 impiegati pagati 3000 il valore restituito sarà calcolato come media tra 1000 e 3000, riportando quindi il valore di 2000. Se non avessimo specificato il predicato DISTINCT il calcolo avrebbe restituito il valore 1000*10 + 3000*3 risultando quindi il valore di 1461. È importante capire questa differenza perché potrebbe produrre risultati inaspettati. Restano le ultime due funzioni di aggregazione: MIN e MAX che, come dicono i loro nomi, restituiscono rispettivamente il valore minimo ed il valore massimo dell'insieme richiesto. Queste due funzioni lavorano bene sia su campi numerici che su campi di tipo carattere. SELECT MIN(nome) AS primo, MAX(nome) AS ultimo FROM dipendenti; Restituirà il primo e l'ultimo alfabeticamente dei dipendenti, cioè quello in cui il campo nome apparirà in prima posizione e quello che sarà in ultima se le righe venissero ordinate. Come per le altre funzioni è possibile specificare il predicato ALL o DISTINCT ma in entrambi i casi di queste due funzioni il loro effetto è inutile; l'inclusione o l'esclusione non comporta alcuna differenza; saranno sempre e comunque recuperati il primo e l'ultimo. SELECT MIN(stipendio) AS povero, MAX(stipendio) AS ricco FROM dipendenti; Naturalmente è possibile effettuare la stessa interrogazione anche su dati numerici e, nel nostro esempio, recuperare lo stipendio minimo e lo stipendio massimo di tutti i dipendenti. 8
Raggruppamenti Le funzioni di aggregazione trattate nell'articolo precedente trovano il loro connubbio naturale con la clausola GROUP BY, utilizzata, come ne dice il nome, per suddividere in gruppi le righe estratte mediante istruzione SELECT. La sintassi generale, molto semplice è la seguente: GROUP BY <campi> È applicata alle selezioni per suddividere i risultati in gruppi distinti per valore nei campi specificati. Spiegare il funzionamento non è semplice e ci avvaleremo di alcuni esempi per renderlo più chiaro. Data la solita selezione dei direttori dalle tabella degli impiegati: SELECT nome, cognome, stipendio FROM impiegati WHERE ruolo='direttore'; Possiamo avere la necessità di recuperare il costo medio oppure totale suddiviso per ruolo. Sappiamo di poter sfruttare le funzioni di aggregazione AVG e SUM per ottenere questi dati ma tutti gli esempi che abbiamo già visto restituivano sempre e soltanto una singola riga, come totale o media di tutte le righe richieste dalla clausola WHERE (o dall'intera tabella in assenza della clausola). Vediamo invece come spaccare il set di risultati in più gruppi, ognuno dei quali con il proprio criterio di aggregazione: SELECT ruolo, AVG(stipendio) AS media, SUM(stipendio) AS somma FROM dipendenti GROUP BY ruolo; Restituirà tre colonne in cui la prima conterrà il ruolo del gruppo di dipendenti, la seconda lo stipendio medio del gruppo cui appartengono e la terza la somma degli stipendi di ogni gruppo di persone: RUOLO MEDIA SOMMA Impiegato 1000 5000 Direttore 3100 9500 È importante capire il funzionamento della clausola GROUP BY e delle funzioni di aggregazione, perché il loro comportamento è ben differente da quello delle altre clausole; affinchè sia possibile il raggruppamento è necessario che tutti i campi coinvolti nella selezione siano raggruppati. Nell'esempio precedente esiste un criterio di raggruppamento dato dal campo ruolo che segue la clausola GROUP BY, mentre gli altri due campi contengono funzioni di aggregazione che, come abbiamo già visto, restituiscono sempre un'unica riga. L'espressione contiene quindi tre campi raggruppati. Il principio di fondo delle funzioni di aggregazione e della clausola GROUP BY è infatti questo: tutti i campi devono rappresentare un raggruppamento, dettato da un'aggregazione oppure da una clausola GROUP BY. Questa è la ragione per cui questa clausola costituisce il complemento delle funzioni viste nell'articolo precedente. Vediamo qualche altro esempio: SELECT ruolo, stipendio, COUNT(stipendio) AS conta, SUM(stipendio) AS somma FROM dipendenti GROUP BY ruolo, stipendio; 9
Questa selezione restituisce lo stipendio, il numero di dipendenti e la spesa totale differenziata per ciascun valore di stipendio. Nell'esempio ciò che riporterà saranno i dati seguenti: RUOLO STIPENDIO CONTA SOMMA Impiegato 1000 5 5000 Direttore 2700 1 2700 Direttore 3400 2 6800 Anche in questo caso tutti i campi sono ragguppati; i primi due sono regolati dalla clausola GROUP BY, gli ultimi due dalle funzioni di aggregazione. Possiamo notare la presenza di due righe con il ruolo Direttore, ma differenziate per stipendio. I cinque impiegati sono invece raggruppati su un'unica riga perchè tutti con lo stesso stipendio. Se il database lamenta qualcosa circa l'assenza di un campo dell'istruzione SELECT all'interno delle clausola GROUP BY oppure delle funzioni di aggregazione la ragione è quella già accennata: tutti i campi dell'istruzione devono essere raggruppati in una delle due maniere già accennate. La clausola HAVING rappresenta un vincolo sui dati risultanti dall'operazione di raggruppamento. Il suo funzionamento è molto simile a quello della clausola WHERE ma anziché operare sui campi del database opera sui raggruppamenti; i campi richiesti possono essere sia quelli delle funzioni di aggregazione sia quelli indicati nelle clausole GROUP BY. Riprendendo l'esempio precedente per estrarre soltanto quelle righe in cui il numero di dipendenti sia maggiore di 1: SELECT ruolo, stipendio, COUNT(stipendio) AS conta, SUM(stipendio) AS somma FROM dipendenti GROUP BY ruolo, stipendio HAVING COUNT(stipendio) > 1; Si tratta dello stesso esempio precedente, ma con l'aggiunta di una clausola HAVING che richiede che il numero di stipendi sia superiore a 1; il suo utilizzo è molto simile a quello della clausola WHERE ma richiede la specifica di un criterio di raggruppamento o aggregazione. Inner Join (giunzione naturale o join interno) La possibilità di suddividere i dati in più tabelle sarebbe inutile se non si potesse unire il contenuto di più tabelle in un unico set di risultati. Un'operazione di JOIN unisce il contenuto di una o più tabelle con l'origine specificata nella clausola FROM; il suo funzionamento è infatti basato sull'uso della clausola FROM e si presenta immediatamente accanto, in un'operazione di selezione: SELECT <campi> FROM <origine> <tipo di join> <origine> [ ON <campo> <relazione> <campo> ]; Anzichè specificare più origini nella clausola FROM la soluzione ideale è quella di specificare un'unica origine in FROM e tutte le altre origini in tante clausole JOIN, ognuna con la propria relazione con l'origine principale. Prima di affrontare in dettaglio il comportamento dell'operatore JOIN è necessaria una presentazione dei diversi tipi di join: 10
INNER JOIN Il JOIN interno, sicuramente il principale, stabilisce che i dati che verranno restituiti sono soltanto quelli che corrispondono al criterio formato dalla relazione dei due campi; tutte le righe che non rientrano nella relazione sono escluse, sia dall'origine principale che da quelle coinvolte nelle relazioni. LEFT OUTER JOIN Il primo dei JOIN esterni, aggiunge ai risultati del JOIN interno anche quelle righe presenti nell'origine presente a sinistra (LEFT) della clausola JOIN; le nuove righe formate da questi dati aggiuntivi sono riempiti con valori NULL. RIGHT OUTER JOIN Il JOIN esterno opposto al precedente, aggiunge ai risultati del JOIN interno anche le righe dell'origine che si trova alla destra (RIGHT) della clausola JOIN; le righe non corrispondenti sono riempite con valori NULL. FULL OUTER JOIN La combinazione di JOIN interno, esterno sinistro ed esterno destro, include tutte le righe presenti nelle orignini a sinistra e a destra della clausola; i dati presenti in una delle origini ma non corrisponti nell'altra conterranno valori NULL. Vediamo in dettaglio la modalità di INNER JOIN. Questo tipo di giunzione si può scrivere anche nel modo seguente: SELECT <campi> FROM <origine>, <origine> WHERE <campo> <relazione> <campo>; A scopo di esempio immaginiamo una situazione di due tabelle contenenti Automobili e Persone PERSONE ID COGNOME NOME 1 Capelli Michele 2 Tardi Giulia 3 Maugeri Martina 4 Catozzo Andrea AUTO TARGA MODELLO PRORIETARIO CD 023 XW Punto 1 AX 765 BC Fiesta 1 AA 125 TY Leon 4 BB 023 UT Panda 5 5 Piconi Gianni In questa presunta realtà abbiamo tre persone (Capelli, Catozzo e Piconi) che possiedono delle automobili, in particolare Capelli ne possiede 2. La forma di JOIN più semplice, combina dei criteri per estrarre soltanto le righe che presentano i campi indicati in entrambe le origini. Data la situazione di analisi precedente è possibile stabilire un JOIN interno che relazioni i due gruppi di persone e auto e riporti soltanto quelle tra loro abbinate. La rappresentazione SQL di questa situazione può essere la presente: 11
SELECT persone.id, cognome, nome, targa, modello FROM persone INNER JOIN auto ON persone.id = auto.proprietario; o in maniera equivalente: SELECT persone.id, cognome, nome, targa, modello FROM persone, auto WHERE persone.id = auto.proprietario; I risultati riportati da entrambe le forme sono i seguenti: ID COGNOME NOME TARGA MODELLO 1 Capelli Michele CD 023 XW Punto 1 Capelli Michele AX 765 BC Fiesta 4 Catozzo Andrea AA 125 TY Leon 5 Piconi Gianni BB 023 UT Panda Le quattro righe della tabella risultante sono quelle per cui è presente l uguaglianza tra i campi id e proprietario, quindi combinano i dati delle automobili con i dati dei relativi proprietari. 12