Lezione 2 - SQL: Relazioni tra tabelle
Che cos'è una relazione?
Relazioni tra tabelle diverse
Parole del linguaggio: INNER JOIN  ... ON
Tipi di relazione: Uno-A-Molti
Tipi di relazione: Uno-A-Uno
Tipi di relazione: Molti-A-Molti
Funzione della tabella EsamiStudenti: osservazione finale
 
Una relazione, naturalmente si parla di database relazionali, è un legame logico che permette di aggregare informazioni.
In un DB una tabella è una relazione, vale a dire una "legge" che mette insieme opportunamente le informazioni 
che individua, a formare righe (record) e colonne (campi) della tabella stessa. 
Spesso è necessario aggregare dati memorizzati in tabelle diverse. 
Un esempio chiarirà il concetto. Se si vogliono elencare gli esami sostenuti dagli studenti degli esempi precedenti,
può essere necessario un insieme di informazioni del tipo:
Elenco esami
| ID | Cognome | Nome | Data Nascita | Esame | Data | Voto | 
| 001 | Moro | Stefano | 06/06/1981 | Analisi 1 | 12/06/2001 | 25 | 
| 001 | Moro | Stefano | 06/06/1981 | Geometria | 13/07/2001 | 28 | 
| 001 | Moro | Stefano | 06/06/1981 | Fisica 1 | 25/07/2001 | 27 | 
| 002 | Banfi | Marco | 26/07/1981 | Analisi 1 | 12/06/2001 | 28 | 
| 002 | Banfi | Marco | 26/07/1981 | Geometria | 20/07/2001 | 21 | 
| 003 | Colombo | Ivan | 31/03/1982 | Analisi 1 | 12/07/2001 | 30 | 
| 003 | Colombo | Ivan | 31/03/1982 | Fisica 1 | 25/07/2001 | 18 | 
In un database correttamente impostato non è proponibile una tabella così strutturata. Infatti si può notare facilmente
come ci siano dati ripetuti diverse volte. 
Che cosa comporta la memorizzazione di informazioni ripetute? Almeno due tipi di inconvenienti:
- Un'occupazione di spazio maggiore: si riporta la stessa informazione più volte
- Una maggiore difficoltà di mantenere i dati coerenti: tutte le copie della stessa informazione devono essere 
sempre identiche
Tutto questo senza contare il maggiore rischio di commettere errori nell'inserimento dati: più si scrive, maggiore è la 
probabilità di sbagliare
In breve, la data di nascita, il nome e il cognome sono informazioni sempre uguali  
per una persona, ma potrebbe essere richiesto di doverle visualizzare come nell'esempio riportato.
 
Relazioni tra tabelle diverse
 
Come si risolve il problema?
Innanzi tutto dividendo le informazioni. Infatti si dovranno memorizzare una sola volta i dati anagrafici di ogni 
studente. Ci sarà per questo una tabella specifica (Studenti). Servirà quindi una seconda tabella (Voti) in cui registrare i dati degli esami 
sostenuti.
| Studenti
| ID_S | Cognome | Nome | Data Nascita | ...Altro |  
| 001 | Moro | Stefano | 06/06/1981 | ... |  
| 002 | Banfi | Marco | 26/07/1981 | ... |  
| 003 | Colombo | Ivan | 31/03/1982 | ... |  | Voti
| ID_S | Esame | Data | Voto |  
| 001 | Analisi 1 | 12/06/2001 | 25 |  
| 001 | Geometria | 13/07/2001 | 28 |  
| 001 | Fisica 1 | 25/07/2001 | 27 |  
| 002 | Analisi 1 | 12/06/2001 | 28 |  
| 002 | Geometria | 20/07/2001 | 21 |  
| 003 | Analisi 1 | 12/07/2001 | 30 |  
| 003 | Fisica 1 | 25/07/2001 | 18 |  | 
 
Il campo ID_S è l'identificatore di uno studente; è la chiave primaria della tabella Studenti, quindi ne identifica univocamente 
ogni record. Nella tabella Voti il campo ID_S è necessario per individuare la persona che ha sostenuto un esame in quella data,
con quella valutazione. Sarà 
l'unico riferimento allo studente presente in quest'ultima tabella. 
Tutte le altre informazioni possono essere recuperate stabilendo una relazione tra la tabella Studenti e la tabella Voti.
 
Parole del linguaggio: INNER JOIN  ... ON
 
La sintassi relativa alla definizione di una relazione tra due tabelle è
nome_tab1 INNER JOIN  nome_tab2  ON  nome_tab1.nome_campo1=nome_tab2.nome_campo2
significa che verranno aggregati record provenienti dalle due tabelle sulla base dell'uguaglianza del contenuto dei due campi 
indicati
 
Istruzione SQL
SELECT STUDENTI.ID_S, STUDENTI.Cognome, STUDENTI.Nome, STUDENTI.Data_Nascita, VOTI.Esame, VOTI.Data, VOTI.Voto
FROM STUDENTI INNER JOIN VOTI ON STUDENTI.ID_S = VOTI.ID_S
 
Per ogni record della tabella Voti (quindi per ogni esame sostenuto da uno studente) vengono individuate le informazioni 
dello studente interessato, prese dalla tabella Studenti
Tipi di relazione: Uno-A-Molti
 
Il tipo di relazione dell'esempio precedente è il più frequente. Si tratta di una relazione Uno-A-Molti (1-M). Significa 
che ad un record della tabella-lato-uno, nel nostro caso Studenti, ne possono corrispondere molti dell'altra tabella (Voti), 
mentre non è vero il contrario. 
In pratica per ogni studente ci saranno diversi record nella tabella Voti, mentre ogni voto (ogni esame sostenuto) farà 
capo ad un unico studente.
Di norma per realizzare una relazione di questo tipo si inserisce nella tabella lato-Molti (nel
nostro caso, Voti) un campo che corrisponde alla la chiave primaria della tabella lato-Uno (Studenti). Questo campo 
aggiunto prende il nome di chiave esterna . Nell'esempio considerato, la chiave esterna per la tabella Voti è il campo ID_S, 
che ha la funzione di chiave primaria nella tabella Studenti.
Tipi di relazione: Uno-A-Uno
 
La relazione più semplice tra due tabelle è quella definita Uno-A-Uno (1-1). Significa che ad un record di una delle due tabelle 
della relazione, ne corrisponde uno dell'altra tabella e viceversa. 
Un esempio anche per questo:
| Studenti
| ID_S | Cognome | Nome | Data Nascita | ...Altro |  
| 001 | Moro | Stefano | 06/06/1981 | ... |  
| 002 | Banfi | Marco | 26/07/1981 | ... |  
| 003 | Colombo | Ivan | 31/03/1982 | ... |  
| 004 | Pozzi | Maurizio | 31/08/1977 | ... |  
| 005 | Tarantini | Andrea | 03/05/1976 | ... |  | Esami di Laurea
| ID_S | Data | Voto |  
| 004 | 12/06/2001 | 94/100 |  
| 005 | 12/06/2001 | 100/100 |  | 
Per ogni studente ci sarà un solo record nella tabella Esami di Laurea, ed ogni voto di laurea è proprio di un solo 
studente. Non è detto che il numero di record delle due tabelle sia uguale. In generale non è così.
Perchè realizzare due tabelle diverse e non mettere tutti i campi in una tabella unica? Nel caso in esame, per esempio,
non tutti gli studenti hanno i dati dell'esame di laurea. Finchè non ci saranno questi dati (per qualcuno non ci saranno mai)
è inutile tenere spazio occupato per campi privi di informazione. Infatti è questo che avverrebbe se avessimo una tabella 
Studenti comprensiva dei campi Data_Laurea e Voto_Laurea.
A partire dalle tabelle 
Studenti (ID_S, Cognome, Nome, Data_Nascita,....) 
Esami di Laurea(ID_S, Data, Voto)
scrivere il codice SQL necessario a realizzare il seguente set di dati:
Studenti Laureati
| ID_S | Cognome | Nome | Data_Nascita | Data | Voto | 
| 004 | Pozzi | Maurizio | 31/08/1977 | 12/06/2001 | 94/100 | 
| 005 | Tarantini | Andrea | 03/05/1976 | 12/06/2001 | 100/100 | 
 
A partire dalle stesse tabelle 
Studenti (ID_S, Cognome, Nome, Data_Nascita,....) 
Esami di Laurea(ID_S, Data, Voto)
scrivere il codice SQL necessario a realizzare il seguente set di dati, ordinato rispetto alla data di nascita, senza che
quest'ultima venga visualizzata:
Studenti Laureati
| ID_S | Cognome | Nome | Data | Voto | 
| 005 | Tarantini | Andrea | 12/06/2001 | 100/100 | 
| 004 | Pozzi | Maurizio | 12/06/2001 | 94/100 | 
 
Tipi di relazione: Molti-A-Molti
 
La situazione più complessa è quella realizzata attraverso una relazione Molti-A-Molti (M-M). In questo caso ad 
ogni record di una delle due tabelle coinvolte possono corrispondere più record nell'altra tabella e viceversa.
Se ne può consideare un'applicazione nell'esempio esaminato degli studenti. Se si rende necessario memorizzare 
ulteriori informazioni relative ad ogni singola materia d'esame, si deve ricorrere all'utilizzo di una tabella specifica per 
gli esami stessi.
MaterieDEsame (
ID_Mat, Nome, Precedenze, N_Ore_annuali, Docente,....)
questa conterrà un record per ogni materia, con le caratteristiche proprie della materia e dell'esame corrispondente. 
In tal caso la relazione tra Studenti e MaterieDEsame è di tipo Molti-A-Molti: ad ogni studente corrispondono 
diversi record nella tabella MaterieDEsame, come ad ogni materia d'esame (ogni record della tabella) corrispondono molti 
studenti
| MaterieDEsame
| ID_Mat | Nome | Preced | N_Ore | Docente |  
| 1 | Analisi 1 | / | ... 
 | ... 
 |  
| 2 | Analisi 2 | 1 | 
 | 
 |  
| 3 | Analisi 3 | 2 | 
 | 
 |  
| 4 | Geometria | / | 
 | 
 |  
| 5 | Fisica 1 | / | 
 | 
 |  
| 6 | Fisica 2 | 5 | 
 | 
 |  | Studenti
| ID_S | Nome | Cognome | Dati | Data_Nascita |  
| 001 | Stefano | Moro | ... | 06/06/1981 |  
| 002 | Marco | Banfi | 
 | 26/07/1981 |  
| 003 | Ivan | Colombo | 
 | 31/03/1982 |  
| 004 | Maurizio | Pozzi | 
 | 31/08/1977 |  
| 005 | Andrea | Tarantini | 
 | 03/05/1976 |  | 
Come si può vedere, tra le due tabelle in questione non esistono informazioni comuni. La relazione può essere creata
attraverso un'ulteriore tabella che farà da tramite. Si chiamerà EsamiStudenti. Nel precedente esempio, relativo alla relazione 1-M, 
una tabella Voti riportava le informazioni sugli esami degli studenti. Ora invece Voti viene sostituita da EsamiStudenti.
La struttura delle tre tabelle e i link che le collegano sono quelli riportati di seguito
 
In questo modo non vengono inserite chiavi intermedie in nessuna delle due 
tabelle di partenza. Sarà la nuova tabella EsamiStudenti che avrà il compito di contenere le chiavi esterne. Così si crea 
una doppia relazione:
- relazione 1-M tra MaterieDEsame (lato 1) e EsamiStudenti (lato M), basata sull'uguaglianza del contenuto dei campi 
 MaterieDEsame.ID_Mat e EsamiStudenti.Nome_Esame
 
- relazione 1-M tra Studenti (lato 1) e EsamiStudenti(lato M), basata sull'uguaglianza del contenuto dei campi 
 Studenti.ID_S e EsamiStudenti.ID_S
 
 
La tabella EsamiStudenti di fatto 
è la relazione di tipo Molti-A-Molti tra Studenti e MaterieDEsame.
La sintassi della query che realizza la relazione M-M, apparentemente complicata, in realtà è semplicemente
la realizzazione della doppia relazione 1-M appena descritta
Istruzione SQL
SELECT STUDENTI.ID_S, STUDENTI.Cognome, MaterieDEsame.Nome_mat, EsamiStudenti.Data_Esame, EsamiStudenti.Voto_Esame
FROM MaterieDEsame INNER JOIN (STUDENTI INNER JOIN EsamiStudenti ON STUDENTI.ID_S = EsamiStudenti.ID_S)
ON MaterieDEsame.ID_Mat = EsamiStudenti.Nome_Esame;
 
Funzione della tabella EsamiStudenti: osservazione finale
Nella tabella EsamiStudenti i campi strettamente necessari per realizzare la relazione M-M sono solo due: ID_S, chiave
primaria della tabella Studenti, e Nome_Esame che corrisponde a ID_Mat, chiave primaria della tabella MaterieDEsame. 
L'esistenza in EsamiStudenti di altri campi, dipende dal fatto che la tabella in questione NON ha il SOLO scopo di 
realizzare la relazione, ma ha una reale funzione nella rappresentazione delle informazioni degli studenti. Infatti, come 
rilevato in precedenza, sostituisce la tabella Voti. 
L'impostazione attuale Studenti - EsamiStudenti - MaterieDEsame, in alternativa alla precedente Studenti - Voti,
permette al DB un maggiore, o migliore, contenuto informativo
Home
Lezione 1
Lezione 3