Fondamenti del linguaggio SQL e l'istruzione SELECT in dettaglio | |||
Il Linguaggio SQL, diventato ormai uno standard mondiale per formulare interrogazioni strutturate a database relazionali, incorpora molti costrutti (o istruzioni) oltre a quella principale denominata SELECT, ma per non divagare in discorsi che potrebbero risultare complessi se trattati in maniera approfondita, limiteremo la trattazione alla sola istruzione di selezione, rimandando l'utente che ne volesse sapere di più, alla consultazione di libri o manuali specifici su SQL, oppure su Microsoft Access. L'istruzione SELECT (in italiano, SELEZIONA) permette di indicare a Business quali dati (Es.: Descrizione, Prezzo, Codice, Quantità, Data, etc.), relativi a una o più entità (Es.: Cliente, Articolo, Ordine, etc.), prelevare dagli archivi, se e come filtrarli (Es.: "solo quelli di Rimini" oppure "solo quelli che costano più di 10000 £", etc.), sulla base di quale dato presentarli in maniera ordinata e/o raggruppata. Di seguito ne è riportata la sintassi: SELECT NomeCampo1, NomeCampo2,....,NomeCampoN Supponiamo esistente una tabella, semplificata rispetto a quella esistente in Business, di nome TbClienti e contenente informazioni sui Clienti e formata dalle seguenti informazioni: Cognome, Nome, Indirizzo, Cap, Città, Provincia, Telefono. Di seguito è riportato un possibile schema della tabella TbClienti:
Ogni riga di questa tabella, eccetto la prima presente solo per motivi descrittivi, rappresenta un record (cioè un gruppo di informazioni relative alla stessa entità, nell'esempio "un Cliente") formato a sua volta da Campi (rappresentati nell'esempio dalle colonne, che specificano le informazioni disponibili per ogni record: Cognome, Nome, Indirizzo, Cap, Città, Provincia, Telefono). Fondamentalmente possiamo pensare gli archivi di Business molto prossimi a questa struttura (cioè una Tabella), con la differenza che il numero delle tabelle è di parecchie decine, e il numero di Campi per ogni tabella varia da 2 a 100 circa. Una SELECT può essere vista come una operazione che prende in ingresso 1 o più tabelle, e ne restituisce una, contenente i risultati della nostra richiesta (Tabella Risultato). Creiamo, ora, una piccola Query (in italiano, INTERROGAZIONE; che non è altro che una istruzione SELECT): specifichiamo la parola chiave SELECT, seguita dal nome dei campi della tabella ( o Tabelle) che vogliamo siano visualizzati nella 'Tabella Risultato'. SELECT Cognome,Nome,Telefono seguiti dalla clausola FROM (in italiano, Da) e il nome della o delle Tabelle a cui appartengono i campi elencati dopo la SELECT (fatto che rende importante conoscere la struttura delle tabelle del database di Business): SELECT Cognome,Nome,Telefono Indicati quali campi vogliamo vedere e stabilite le tabelle a cui questi campi appartengono, abbiamo già fornito le indicazioni minime indispensabili per poter eseguire la query. Il risultato di questa query sarà una tabella ('Tabella Risultato') avente lo stesso numero di record (righe) della tabella TbClienti, ma solo 3 dei 7 campi della tabella TbClienti (abbiamo, cioè, limitato la visualizzazione di informazioni relative ad ogni cliente (riga) e NON, attenzione, al numero di clienti (righe) che rimane sempre 4) . Ecco, di seguito, la 'Tabella Risultato' della query:
Supponiamo ora di voler vedere le stesse informazioni ma dei soli Clienti della provincia di Rimini: SELECT Cognome,Nome,Telefono Ed ecco il risultato di questa nuova query:
a tal fine abbiamo utilizzato la clausola WHERE (in italiano, Dove) attraverso cui possiamo indicare anche più condizioni (o filtri) nello stesso modo utilizzato per i Filtri Utente: SELECT Cognome,Nome,Telefono In questo caso, insieme ai Clienti della provincia di Rimini, verranno visualizzati nella 'Tabella Risultato' anche i clienti della provincia di Milano. (OR = oppure).
Se proviamo a leggere la query traducendo le sue clausole in italiano, notiamo che è un linguaggio abbastanza naturale dal punto di vista della comprensione: - "SELEZIONA Cognome,Nome,Telefono DA TbClienti DOVE Provincia UGUALE 'RN' OPPURE Provincia UGUALE 'MI'". Una istruzione di SELECT può, come abbiamo già detto, selezionare dati anche da più tabelle contemporaneamente. Facciamo un esempio, supponendo esistenti 2 tabelle così strutturate:
La Tabella TbDipendenti contiene il campo 'Codice del Dipendente', affinchè ogni dipendente sia univocamente identificato (anche in caso di omonimia), il campo 'Cognome', il campo 'Nome' e il campo 'Codice del Reparto' presso cui il Dipendente è impiegato. La Tabella TbReparti contiene il campo 'Codice del Reparto', il Campo 'Descrizione del Reparto', il campo 'Orario' e il campo 'Cognome del Capo-reparto'. Proviamo a scrivere una query semplice: SELECT TbDipendenti.Cognome, TbReparti.Descrizione, TbReparti.CapoReparto Riportiamo di seguito il risultato della query:
Premettiamo che il risultato potrebbe apparire poco significativo, in quanto il programma, che ha elaborato la nostra query, si è limitato, giustamente, a fornire tutte le combinazioni possibili dei record della tabella TbDipendenti con quelli della tabella TbReparti (il cliente 'Rossi' combinato prima con il Reparto 'Produzione' e poi col Reparto 'Controllo Q' e stessa cosa per i restanti 3 clienti), visualizzando poi solo i valori dei campi che noi abbiamo elencato di seguito alla parola chiave SELECT (TbDipendenti.Cognome, TbReparti.Descrizione, TbReparti.CapoReparto). I Record ritornati nella 'Tabella Risultato' sono 8, ottenuti, infatti, dai 4 della Tabella TbDipendenti combinati (quindi moltiplicati) con i 2 della Tabella TbReparti. Tecnicamente si dice che viene restituito il 'Prodotto Cartesiano' delle n Tabelle elencate nella clausola FROM. Tenendo presente questo meccanismo, in base al quale ogni volta che nella clausola FROM (Da) appaiono due o più tabelle, il risultato sarà una combinazione di tutti i record della prima con tutti quelli della seconda, proviamo, immediatamente, a costruire una Query più significativa: supponiamo di voler sapere in che reparto lavora la Sig.ra Bianchi: SELECT TbReparto.CodiceReparto, TbReparto.Descrizione Di seguito è riportato il risultato della query appena descritta:
I campi riportati sono due (TbReparto.CodiceReparto, TbReparto.Descrizione), perché due sono i campi listati di seguito alla istruzione SELECT. Da notare che al nome dei campi (CodiceReparto, Descrizione) è stato fatto precedere il nome della tabella separata da un punto("TbReparto."), per evitare errori qualora ci siano campi con nomi uguali, appartenenti a tabelle diverse (come nel nostro caso con CodiceReparto, presente in entrambe le tabelle TbReparti e TbDipendenti). Si consiglia di utilizzare sempre questa convenzione. Nella clausola FROM (Da), invece, troviamo elencati i nome delle due tabelle, anche se non richiediamo alcuna visualizzazione dei campi della tabella TbDipendenti; ciò perché abbiamo bisogno di avere tutte le combinazioni fra le due tabelle, come nell'esempio precedente, da cui, poi, selezionare solo quelle che ci interessano ai fini dell'ottenimento del risultato che ci aspettiamo. Infatti per poter selezionare i soli dati relativi alla Signora Bianchi, abbiamo specificato che il campo Cognome, che è un campo di TbDipendenti, deve essere uguale a "Bianchi" (quindi, saranno scartate tutte le combinazioni NON aventi nel campo TbDipendenti.Cognome il valore 'Bianchi'). La seconda condizione, unita alla prima tramite l'operatore logico "AND", viene tecnicamente chiama "JOIN" cioè "Collegamento". è, infatti, quest'ultima, che ci permette di visualizzare la Descrizione associata al CodiceReparto 'R2' che è il valore presente anche, nel campo CodiceReparto del record relativo alla Signora 'Bianchi' nella tabella TbDipendenti. Possiamo dire, in altre parole, che la Join "collega" i dati della tabella TbDipendenti con i relativi e corrispondenti dati della TbReparti (costringe, cioè, il motore SQL a scartare tutte quelle combinazioni di record delle due tabelle in cui NON si ha che il CodiceReparto di TbDipendenti sia UGUALE al CodiceReparto di TbReparti). Proviamo, ora, a richiedere Nome e Cognome di tutti i dipendenti che lavorano nel reparto 'Produzione'. SELECT TbDipendenti.Cognome, TbDipendenti.Nome Quanto segue, ne costituisce il risultato:
Nella SELECT è stato richiesto il contenuto dei campi Cognome e Nome della tabella TbDipendenti. Nella Clausola FROM (Da) sono state nuovamente specificate entrambe le tabelle, affinchè il programma esegua il 'Prodotto Cartesiano' tra le tabelle in questione. Nella Clausola WHERE (Dove) troviamo la solita JOIN (collegamento), che collega la tabella TbDipendenti con la tabella TbReparti attraverso il campo CodiceReparto (ma che praticamente non è altro che la condizione che scarta tutte le combinazioni in cui TbDipendenti.CodiceReparto e TbReparti.CodiceReparto sono diversi), e la condizione che impone la selezione di tutte e solo le combinazioni di record che hanno nel campo TbReparti.Descrizione il valore 'Produzione'. Se alla query precedente aggiungiamo la clausola ORDER BY (in italiano, ORDINATE PER), è possibile variare l'ordine di visualizzazione dei record nella 'Tabella Risultato'. Es.: SELECT TbDipendenti.Cognome, TbDipendenti.Nome In questo modo la 'Tabella Risultato' sarà ordinata in base al campo Cognome, e in caso di uguaglianza del campo Cognome, in base al campo Nome e in caso di uguaglianza anche del Campo Nome, in ordine di disposizione nelle tabelle di origine (TbDipendenti).
L'ultima Clausola applicabile, è quella denominata GROUP BY (in italiano, RAGGRUPPATI PER). Essa ci permette di raggruppare i record (righe) in base a campi che hanno gli stessi valori e attraverso la sotto-clausola HAVING (in Italiano, AVENTI) eliminare i raggruppamenti che non ci interessano. In altre parole, occorre utilizzare la clausola WHERE (Dove) per escludere le righe che non si desidera raggruppare e occorre utilizzare la clausola HAVING (Aventi) per filtrare i record dopo che sono stati raggruppati.Es: SELECT TbReparti.Descrizione, SUM(TbDipendenti.Stipendio) Attraverso la Query precedente si ottiene, un raggruppamento dei dipendenti per reparto di lavoro e attraverso la funzione SUM(stipendio) si ottiene la somma degli stipendi dei dipendenti raggruppati per reparto. Le funzioni tipo SUM (Avg, Count, Min, Max) non sono attualmente inseribili tramite il Generatore di Query. Nell'eventualità, è lasciato all'utente il compito di inserirlo manualmente.
La sintassi delle condizioni inseribili nella clausola HAVING (Aventi) rispondono alle stesse regole delle condizioni della clausola WHERE (Dove), con la differenza che possono essere oggetto di condizione solo i Campi elencati dopo la Clausola GROUP BY (Raggruppati per). |