INTRODUZIONE
Se la definizione dello schema della base di dati non è
fatto ad hoc, può succedere che si abbiano delle anomalie nel database,
quali, per esempio, la ripetizione delle informazioni con spreco di tempo
(per l’inserimento dei dati) e di spazio (memoria).
La teoria della normalizzazione ha come scopo quello di fornire
metodi per progettare basi di dati senza anomalie. In pratica la normalizzazione
consente di verificare se la definizione dello schema corrisponde a dei
“canoni standard” di correttezza della base di dati. Dopo aver definito
lo schema, si devono seguire alcune regole per rendere le tabelle in quelle
che sono chiamate le FORME NORMALI, cioè per fare in modo
che lo schema corrisponda ai “canoni standard”.
La teoria della normalizzazione è un argomento ampio, difficile
da capire e pieno di termini tecnici. In questo manuale, che ha lo scopo
di insegnare ad utilizzare Access e non di sostituire un testo per la
teoria dei database, gli argomenti relativi alla normalizzazione saranno
trattati in modo più semplice, senza l’introduzione di concetti
e termini troppo impegnativi. Alcuni termini introdotti non sono propriamente
corretti, considerando la teoria delle basi di dati, ma sono molto più
semplici da capire rispetto a quelli utilizzati in ambito universitario.
I metodi descritti in seguito sono solo quelli principali e sono “adattati”
per una comprensione più facile.
Riassumiamo la teoria della normalizzazione nelle seguenti regole per
creare in modo corretto le tabelle:
- ogni tabella deve avere una chiave primaria
- ogni campo deve contenere un solo valore;
- i campi di una tabella non devono dipendere da altri campi (esclusa
la chiave primaria);
- evitare le ripetizioni e la ridondanza dei dati.
OGNI TABELLA DEVE AVERE UNA CHIAVE PRIMARIA
La chiave primaria è già stata definita nel capitolo
precedente.
Dopo la stesura dello schema, la prima cosa che si deve verificare,
sempre nella fase di progettazione, è che ogni tabella abbia
una chiave primaria. In ogni tabella si deve trovare un campo che non
contenga ripetizioni e che rappresenti ogni record nelle altre tabelle
(tra le chiavi candidate). Se non esiste un campo con tali caratteristiche,
si deve aggiungere un nuovo campo. Il nuovo campo non risulta dall’analisi
dei requisiti, in quanto non sarebbe necessario per l’esistenza della
tabella, ma è necessario per creare una tabella senza anomalie,
cioè in una forma normale (che si presume corretta).
ESEMPIO. Ordini.
La figura 6.01 visualizza la tabella degli ordini risultante da una
possibile analisi dei requisiti.
FIG. 6.01
La tabella non contiene chiavi candidate, infatti ogni colonna contiene
ripetizioni. SI deve aggiungere un nuovo campo, che di solito prende
il nome di ID, che sta per IDENTIFICATORE. La figura 6.01
visualizza la tabella, in forma normale, con il nuovo campo chiave primaria:
IdOrdine.
FIG. 6.02
PRIMA FORMA NORMALE
Ogni campo deve contenere un solo valore: PRIMA FORMA NORMALE,
chiamata anche FORMA ATOMICA.
Se una tabella si trova nella prima forma normale, non c’è alcuna
possibilità di suddividere ulteriormente i campi della tabella.
I motivi per cui non si devono avere campi che contengono più
di un valore risiedono nella definizione stessa dei database relazionali.
Non sono tutti semplici da capire, di seguito si elencano i principali.
- I database relazionali non sono in grado di fare ricerche, efficienti,
se il campo considerato contiene più di un valore all’interno.
- Le relazioni non possono esistere su campi contenenti più
valori.
Ci sono altri motivi, ma non vale la pena di analizzarli in questa
sede.
Quando si incontrano campi che contengono più valori, questi
campi essere suddivisi in modo che contengano un unico valore su ogni
record.
In alcuni casi la suddivisione è semplice e naturale, in altri
è molto più complessa.
Come al solito, gli esempi valgono molto più delle parole.
ESEMPIO. Indirizzo.
La figura 6.03 visualizza una tabella Persone (con solo i campi più
interessanti).
FIG. 6.03
La tabella ha una chiave primaria, quindi la prima regola è
confermata. Il campo Indirizzo, però, contiene più valori
di “tipo” diverso. È possibile fare ricerche sul campo indirizzo
definito in questo modo, ma risultano molto lente, perché non
si devono confrontare due parole, ma intere frasi composte di più
parti (via, nome della via, numero civico e città). Per esempio,
trovare tutte le persone che abitano nella stessa città, con
questa definizione del campo indirizzo, risulta complesso. Conviene
suddividere il campo indirizzo, come nelle tabelle viste fino ad ora,
figura 6.04.
FIG. 6.04
Questa è la suddivisione in cui si trova di solito il campo
indirizzo nelle tabelle. Con questa nuova definizione è molto
più veloce la ricerca delle persone che abitano nella stessa
città.
Non sempre questa è la forma migliore, dipende dalle operazioni
che si devono fare sulla base di dati. Si supponga che la tabella serva
per un elenco telefonico, in cui si effettuano ricerche anche sui nomi
delle vie. Anche in questo caso la ricerca risulterebbe lenta e macchinosa,
per cui si deve suddividere ulteriormente la tabella, come mostrato
nella figura 6.05.
FIG. 6.05
Per sapere fino a dove suddividere il campo si deve consultare l’analisi
dei requisiti. In generale, tutti i campi che servono per confronti
o ricerche, nel normale utilizzo del database, devono essere suddivisi.
ESEMPIO. Telefono.
Le stesse osservazioni fatte in precedenza volgono per il numero di
telefono. Si consideri la tabella visualizzata nella figura 6.06.
FIG. 6.06
La tabella ha una chiave primaria, IdPersona, quindi la prima regola
è assicurata. Il campo Telefono potrebbe essere corretto per
molti archivi, ma, se si vogliono fare ricerche sulle colonne telefono,
queste risulterebbero troppo lunghe e macchinose. La figura 6.07 visualizza
una possibile suddivisione del campo Telefono.
FIG. 6.07
SECONDA FORMA NORMALE
Tutti i campi, diversi dalla chiave primaria, devono dipendere solo
dal valore della chiave primaria. I campi delle tabelle non devono dipendere
da altri campi, esclusa la chiave primaria. Questo garantisce che la
chiave primaria rappresenti in modo univoco ogni record della tabella
e che non si possano fare calcoli sui campi delle tabelle.
ESEMPIO. Ordini.
La figura 6.08 visualizza una tabella Ordini, nella prima forma normale:
la tabella ha una chiave primaria, IdOrdine e non ci sono campi che
contengono più di un valore.
FIG. 6.08
Il problema è che il campo TotaleFattura dipende dai campi Quantità
e PrezzoUnitario. Se venisse modificato il valore del campo Quantità,
dovrebbe essere modificato anche il valore del rispettivo campo TotaleFattura.
La tabella, quindi, non è nella seconda forma normale. Il campo
TotaleFattura deve essere eliminato dalla tabella, per trovare il totale
della fattura si devono utilizzare le query. Le tabelle non possono
contenere valori calcolati.
La figura 6.09 visualizza la tabella nella seconda forma normale.
FIG. 6.09
ESEMPIO. Età.
Un altro campo che non corrisponde alla seconda forma normale è
il campo età, in quanto dipende dalla data di nascita e dalla
data corrente. Il campo età deve essere eliminato dalla maggior
parte delle tabelle.
Esistono situazioni in cui i campi età e TotaleFattura possono
essere utilizzati nelle tabelle: quando questi campi rappresentano una
situazione statica, che non si modifica nel tempo. Per esempio se il
campo età contiene l’informazione relativa all’età delle
persone al 31/12/2010, questo campo non dipende da altri valori, quindi
può esistere e le tabelle si trovano nella seconda forma normale.
EVITARE LE RIPETIZIONI
Quando su una tabella i valori di alcuni campi sono ripetuti, si deve
scomporre la tabella in due parti. Si creano praticamente due nuove
tabelle che contengono i campi di quella presa in considerazione. Le
nuove tabelle devono poi essere messe in relazione tra loro.
ESEMPIO.
Si vuole tenere conto di tutti gli acquisti fatti dai clienti. Se si
organizzano i dati in un’unica tabella, molte informazioni devono essere
ripetute (il nome, l’indirizzo e tutti i dati del cliente per ogni ordine).
La figura 6.10 visualizza la situazione.
FIG. 6.10
È visibile la notevole ripetizione dei dati, con grande spreco
di tempo (per l’inserimento) e di memoria (hard disk e RAM).
Le situazioni di questo tipo indicano, in genere, che la tabella memorizza
più di un oggetto, cioè più elementi distinti.
Nella tabella 6.10 sono rappresentati le informazioni dei clienti e
quelle degli ordini effettuati dai clienti stessi. La persona cliente
è un oggetto, l’ordine effettuato è un altro oggetto.
Si deve scomporre la tabella in due parti, che rappresentino rispettivamente
questi due oggetti: una tabella Clienti e una tabella Ordini. Si devono
“spartire” i campi della tabella iniziale, nei due nuovi insiemi, considerando
se le informazioni riguardano uno o l’altro oggetto. La figura 6.11
visualizza la separazione delle tabelle.
FIG. 6.11
Queste tabelle non rispettano la prima regola, manca infatti la chiave
primaria. Si deve aggiungere, in entrambe, un campo chiave primaria,
figura 6.12.
FIG. 6.12
Le due tabelle sono in forma normale (prima e seconda), ma non è
possibile sapere da chi sono stati effettuati gli ordini, manca la relazione.
Come visto più volte, la relazione tra clienti e ordini è
del tipo uno a molti, la tabella Clienti è il lato uno, la tabella
Ordini è il lato molti. Si deve aggiungere la chiave esterna
nella tabella lato molti (Ordini), il campo da aggiungere deve essere
uguale al campo chiave primaria della tabella lato uno (Clienti). Quindi,
si aggiunge il campo IdCliente nella tabella Ordini, il risultato finale
è visualizzato nella figura 6.13.
FIG. 6.13
CONCLUSIONI
Dopo la definizione dello schema della base di dati, si deve controllare
tutta la struttura definita, controllando una ad una le tabelle. Si
deve passare tutto lo schema per verificare se sono rispettate le regole
descritte nel capitolo, un passaggio completo (tabella per tabella)
per ogni regola. Questo conclude la fase di progettazione, si passa
poi alla successiva, cioè la realizzazione, nel nostro caso con
Access 2000.