La Normalizzazione delle Basi di Dati
La normalizzazione è un processo di organizzazione dei dati in un database relazionale che ha l'obiettivo di ridurre la ridondanza dei dati e migliorare l'integrità delle informazioni.
Attraverso il progressivo soddisfacimento di una serie di regole chiamate forme normali, si trasforma progressivamente una tabella "grezza" in un insieme di tabelle ben strutturate, eliminando i problemi che possono verificarsi durante le operazioni di inserimento, aggiornamento e cancellazione.
Parte Teorica – Introduzione alla Normalizzazione
Perché Normalizzare?
Consideriamo una situazione reale: un'azienda che gestisce ordini dei clienti. Un impiegato inesperto potrebbe creare una singola tabella contenente tutte le informazioni:
Esempio di Tabella NON Normalizzata
| CodiceOrdine |
DataOrdine |
Cliente |
IndirizzoCliente |
TelefonoCliente |
Prodotti |
Quantità |
PrezzoUnitario |
Venditore |
EmailVenditore |
| ORD001 |
2024-01-15 |
Mario Rossi |
Via Roma 10, Milano |
02-1234567 |
Laptop Mouse Tastiera |
1 2 1 |
1200 18 35 |
Giulia Bianchi |
[email protected] |
| ORD002 |
2024-01-16 |
Mario Rossi |
Via Roma 10, Milano |
02-1234567 |
Monitor |
1 |
150 |
Giulia Bianchi |
[email protected] |
| ORD003 |
2024-01-17 |
Anna Verdi |
Via Dante 5, Roma |
06-7654321 |
Laptop Cuffie |
2 2 |
1200 50 |
Marco Neri |
[email protected] |
Questa tabella presenta numerosi problemi evidenziati in rosso. Vediamo quali conseguenze negative comportano questi problemi nelle operazioni quotidiane sul database.
I Problemi di una Tabella Non Normalizzata
🔴 Problema di INSERIMENTO
Situazione: L'azienda assume un nuovo venditore, "Luca Verdi" con email "[email protected]".
Problema: Non possiamo inserire le informazioni su questo nuovo venditore finché non effettua almeno una vendita ad un cliente! La tabella richiede un CodiceOrdine, una data, un cliente, ecc. Ma il venditore esiste già, anche se non ha ancora venduto nulla.
Stesso problema per i clienti: Un potenziale cliente che chiede informazioni non può essere registrato finché non effettua un ordine.
🔴 Problema di AGGIORNAMENTO (Modifica)
Situazione: Il cliente "Mario Rossi" si trasferisce da "Via Roma 10, Milano" a "Via Manzoni 20, Milano".
Problema: I dati di Mario Rossi sono ripetuti in più righe (ORD001 e ORD002). Dobbiamo ricordarci di aggiornare tutte le righe che lo contengono. Se dimentichiamo anche solo una riga, avremo dati inconsistenti: lo stesso cliente apparirà con due indirizzi diversi!
Stesso problema per i venditori: Se Giulia Bianchi cambia email, dobbiamo aggiornare tutte le righe dove appare.
🔴 Problema di CANCELLAZIONE
Situazione: L'ordine ORD003 viene annullato e deve essere rimosso dal sistema.
Problema: Anna Verdi ha effettuato solo quell'ordine. Cancellando ORD003, perdiamo completamente tutti i dati di Anna Verdi: nome, indirizzo, telefono. Non sapremo più che esiste come cliente!
Conseguenza: Perdiamo informazioni preziose che potrebbero servire per contattare il cliente in futuro.
🔴 Problema della RIDONDANZA
Osservazione: I dati di "Mario Rossi" (nome, indirizzo, telefono) sono memorizzati identici in ogni suo ordine. I dati di "Giulia Bianchi" (nome, email) sono ripetuti in ogni ordine che gestisce.
Conseguenze:
- Spreco di spazio di archiviazione (con migliaia di ordini diventa significativo)
- Maggiore probabilità di errori durante l'inserimento dei dati
- Difficoltà nel mantenere i dati coerenti
🔴 Problema degli ATTRIBUTI MULTIVALORE
Osservazione: Il campo "Prodotti" contiene più valori (es. "Laptop, Mouse, Tastiera").
Conseguenze pratiche:
- Come posso cercare tutti gli ordini che contengono "Mouse"? Devo fare ricerche complesse su stringhe.
- Come conto quanti Mouse sono stati venduti in totale? Impossibile senza elaborazioni complesse.
- Come associo quantità e prezzi ai singoli prodotti? La struttura non lo permette.
🔴 Problema degli ATTRIBUTI COMPOSTI
Osservazione: Il campo "Cliente" contiene nome e cognome insieme ("Mario Rossi"). Il campo "IndirizzoCliente" contiene via e città insieme.
Conseguenze pratiche:
- Come posso ordinare i clienti per cognome? Devo estrarre il cognome dalla stringa.
- Come posso filtrare gli ordini dei clienti di Milano? Devo cercare "Milano" all'interno della stringa.
- Difficoltà nelle ricerche, negli ordinamenti e nelle statistiche.
La Soluzione: Le Forme Normali
Per risolvere tutti questi problemi, applichiamo progressivamente tre forme normali. Ogni forma normale risolve un tipo specifico di problema e richiede che la forma precedente sia già soddisfatta. Per ricondurre ad una forma normale una tabella si scompone la tabella considerata in altre tabelle ognuna delle quali soddisfa le ipotesi che definiscono la forma normale considerata (ovviamente chi svolge l'esercizio di normalizzazione dovrà verificarlo). Pertanto un esercizio di normalizzazione avverrà per passi: prima assicurarsi che sia in 1FN ovvero che siano verificate le tre proprietà che la caratterizzano e se non lo è scomporla in tabelle che la verificano; poi assicurarsi che le tabelle ottenute siano in 2FN ovvero che siano in 1FN (ma questo era noto dal passo precedente), che per ognuna di esse siano verificate le proprietà che caratterizzano la 2FN e se non lo sono scomporle in tabelle che le verificano; poi assicurarsi che le tabelle ottenute siano in 3FN ovvero che siano in 2FN (ma questo era noto dal passo precedente), che per ognuna di esse siano verificate le proprietà che caratterizzano la 3FN e se non lo sono scomporle in tabelle che le verificano.
Prima Forma Normale (1NF)
Definizione: Una tabella è in
Prima Forma Normale (1NF) se e solo se:
- Non ci sono attributi composti: ogni attributo deve contenere un valore atomico (ovvero non scomponibile in altri attributi)
- Non ci sono attributi multivalore: ogni cella deve contenere un solo valore, non liste o insiemi di valori (ovvero non ci possono essere più valori dell'attributo riferiti alla stessa riga)
- Esiste una chiave primaria: deve essere possibile identificare univocamente ogni riga
Verifica della 1NF sulla tabella di esempio
Verifica 1NF per la tabella iniziale:
- Attributi atomici: ❌ Attributi composti presenti:
- "Cliente" contiene nome e cognome insieme (es. "Mario Rossi")
- "IndirizzoCliente" contiene via e città insieme (es. "Via Roma 10, Milano")
- "Venditore" contiene nome e cognome insieme
- Assenza di attributi multivalore: ❌ Attributo multivalore presente:
- "Prodotti" contiene più valori (es. "Laptop, Mouse, Tastiera")
- Chiave primaria definita: ✅ CodiceOrdine può essere la chiave primaria.
Conclusione: La tabella NON è in 1NF. Dobbiamo risolvere i problemi degli attributi composti e multivalore.
Trasformazione in 1NF
Problema degli attributi composti: Scomponiamo gli attributi composti in attributi atomici:
- "Cliente" → "NomeCliente" + "CognomeCliente"
- "IndirizzoCliente" → "Via" + "Numero" + "Città"
- "Venditore" → "NomeVenditore" + "CognomeVenditore"
Problema degli attributi multivalore: Per gli attributi multivalore "Prodotti", "Quantità" e "PrezzoUnitario" creiamo una tabella separata, in cui ogni riga è formata dalla chiave primaria della tabella iniziale (o, se la chiave primaria è composta da più attributi, dall'attributo/attributi della chiave primaria legati logicamente all'attributo multivalore) e da un valore degli attributi multivalore. Poiché Prodotto, Quantità e PrezzoUnitario sono strettamente correlati tra loro (si riferiscono tutti alla stessa riga di ordine-prodotto), li raccogliamo in una singola tabella.
Tabella Ordini (in 1NF):
| CodiceOrdine |
DataOrdine |
NomeCliente |
CognomeCliente |
Via |
Numero |
Città |
TelefonoCliente |
NomeVenditore |
CognomeVenditore |
EmailVenditore |
| ORD001 | 2024-01-15 | Mario | Rossi | Via Roma | 10 | Milano |
02-1234567 | Giulia | Bianchi | [email protected] |
| ORD002 | 2024-01-16 | Mario | Rossi | Via Roma | 10 | Milano |
02-1234567 | Giulia | Bianchi | [email protected] |
| ORD003 | 2024-01-17 | Anna | Verdi | Via Dante | 5 | Roma |
06-7654321 | Marco | Neri | [email protected] |
Chiave primaria: CodiceOrdine
Tabella ProdottiOrdine (in 1NF):
| CodiceOrdine | Prodotto | Quantità | PrezzoUnitario |
| ORD001 | Laptop | 1 | 1200 |
| ORD001 | Mouse | 2 | 18 |
| ORD001 | Tastiera | 1 | 35 |
| ORD002 | Monitor | 1 | 150 |
| ORD003 | Laptop | 2 | 1200 |
| ORD003 | Cuffie | 2 | 50 |
Chiave primaria: (CodiceOrdine, Prodotto)
Verifico che tutte le tabelle ottenute sono in 1NF:
Verifica 1NF per la tabella Ordini:
- Attributi atomici: ✅ Tutti gli attributi sono atomici. Gli attributi composti sono stati scomposti:
- "Cliente" → "NomeCliente" + "CognomeCliente"
- "IndirizzoCliente" → "Via" + "Numero" + "Città"
- "Venditore" → "NomeVenditore" + "CognomeVenditore"
- Assenza di attributi multivalore: ✅ Ogni cella contiene un solo valore. La colonna "Prodotti" è stata rimossa.
- Chiave primaria definita: ✅ CodiceOrdine è la chiave primaria e identifica univocamente ogni riga.
Verifica 1NF per la tabella ProdottiOrdine:
- Attributi atomici: ✅ Tutti gli attributi sono atomici (CodiceOrdine, Prodotto, Quantità, PrezzoUnitario).
- Assenza di attributi multivalore: ✅ Ogni cella contiene un solo valore. Il problema multivalore è risolto creando una riga separata per ogni prodotto di ogni ordine.
- Chiave primaria definita: ✅ (CodiceOrdine, Prodotto) è la chiave primaria e identifica univocamente ogni riga.
✅ Le tabelle Ordini e ProdottiOrdine sono ora in 1NF.
Seconda Forma Normale (2NF)
Definizione: Una tabella è in
Seconda Forma Normale (2NF) se e solo se:
- È già in 1NF
- Sono assenti attributi che dipendono da una sola parte della chiave primaria: ogni attributo non-chiave deve dipendere dall'intera chiave primaria, non solo da una sua parte
Nota: Se la chiave primaria è formata da un solo attributo, la tabella è automaticamente in 2NF (una volta verificata la 1NF).
Verifica della 2NF
Dobbiamo verificare la 2NF per ogni tabella ottenuta al passo precedente (Ordini e ProdottiOrdine). Per la definizione, verifico per ciascuna: (1) è già in 1NF (sì, dal passo 1); (2) non ci sono attributi che dipendono da una sola parte della chiave primaria.
Verifica 2NF per la tabella Ordini:
- Già in 1NF: ✅ Verificato nel passo precedente.
- Assenza di dipendenze parziali: ✅ La chiave primaria è composta da un solo attributo (CodiceOrdine), quindi per definizione non ci possono essere attributi che dipendono da una sola parte della chiave primaria. La tabella è automaticamente in 2NF.
Verifica 2NF per la tabella ProdottiOrdine:
- Già in 1NF: ✅ Verificato nel passo precedente.
- Assenza di dipendenze parziali: ❌ La chiave primaria è composta da (CodiceOrdine, Prodotto). L'attributo PrezzoUnitario dipende solo da Prodotto (parte della chiave), non dall'intera chiave. La tabella NON è in 2NF.
La tabella ProdottiOrdine non è in 2NF. Per portarla in 2FN, ovvero scomporla in tabelle in 2FN , applico il procedimento: per ogni dipendenza parziale individuata, creo una tabella formata dalla parte di chiave da cui dipendono gli attributi (che diventa la chiave primaria della nuova tabella) più gli attributi che ne dipendono. La tabella originale viene ridotta ai soli attributi che dipendono dall'intera chiave, mantenendo come chiave primaria quella originaria. Nel nostro caso:
- PrezzoUnitario dipende solo da Prodotto → creo la tabella Prodotti con chiave primaria Prodotto e attributo PrezzoUnitario.
- Nella tabella originaria resta solo Quantità (che dipende dall'intera chiave CodiceOrdine, Prodotto) → diventa la tabella DettagliOrdine con chiave primaria (CodiceOrdine, Prodotto).
Tabella Prodotti (✅ 2NF):
| Prodotto | PrezzoUnitario |
| Laptop | 1200 |
| Mouse | 25 |
| Tastiera | 50 |
| Monitor | 300 |
| Cuffie | 80 |
Chiave primaria: Prodotto
Tabella DettagliOrdine (✅ 2NF):
| CodiceOrdine | Prodotto | Quantità |
| ORD001 | Laptop | 1 |
| ORD001 | Mouse | 2 |
| ORD001 | Tastiera | 1 |
| ORD002 | Monitor | 1 |
| ORD003 | Laptop | 2 |
| ORD003 | Cuffie | 2 |
Chiave primaria: (CodiceOrdine, Prodotto)
Verifica 2NF per la tabella Prodotti:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (Prodotto).
- Assenza di dipendenze parziali: ✅ La chiave primaria è composta da un solo attributo (Prodotto), quindi per definizione non ci possono essere attributi che dipendono da una sola parte della chiave primaria. La tabella è automaticamente in 2NF.
Verifica 2NF per la tabella DettagliOrdine:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (CodiceOrdine, Prodotto).
- Assenza di dipendenze parziali: ✅ L'unico attributo non-chiave è Quantità. Quantità dipende dall'intera chiave (CodiceOrdine, Prodotto): la quantità di un prodotto specifico in un ordine specifico. Non ci sono attributi che dipendono solo da una parte della chiave.
✅ Le tabelle Ordini, Prodotti e DettagliOrdine sono ora in 2NF.
Terza Forma Normale (3NF)
Definizione: Una tabella è in
Terza Forma Normale (3NF) se e solo se:
- È già in 2NF
- Sono assenti attributi che dipendono da attributi che non sono chiave primaria: ogni attributo non-chiave deve dipendere direttamente dalla chiave primaria, non da altri attributi non-chiave
Verifica della 3NF
Dobbiamo verificare la 3NF per ogni tabella ottenuta al passo precedente (Ordini, Prodotti, DettagliOrdine). Per la definizione, verifico per ciascuna: (1) è già in 2NF (sì, dal passo 2); (2) non ci sono attributi non-chiave che dipendono da altri attributi non-chiave.
Verifica 3NF per la tabella Ordini:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ❌ Ci sono attributi che dipendono da attributi che non sono chiave primaria:
- Via, Numero, Città, TelefonoCliente dipendono da (NomeCliente, CognomeCliente) che non è chiave primaria
- EmailVenditore dipende da (NomeVenditore, CognomeVenditore) che non è chiave primaria
La tabella NON è in 3NF.
Verifica 3NF per la tabella Prodotti:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ L'unico attributo non-chiave è PrezzoUnitario, che dipende direttamente dalla chiave primaria Prodotto. Non ci sono attributi che dipendono da altri attributi non-chiave. La tabella è in 3NF.
Verifica 3NF per la tabella DettagliOrdine:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ L'unico attributo non-chiave è Quantità, che dipende direttamente dalla chiave primaria (CodiceOrdine, Prodotto). Non ci sono attributi che dipendono da altri attributi non-chiave. La tabella è in 3NF.
Solo la tabella Ordini non è in 3NF. Per scomporla applico il procedimento: per ogni dipendenza transitiva individuata, creo una tabella formata dall'attributo non-chiave da cui dipendono gli altri attributi (che diventa chiave primaria della nuova tabella) più gli attributi che ne dipendono. La tabella originale viene ridotta sostituendo gli attributi estratti con la chiave primaria della nuova tabella (chiave esterna). Nel nostro caso:
- Via, Numero, Città, TelefonoCliente dipendono da (NomeCliente, CognomeCliente) → creo la tabella Clienti con chiave primaria CodiceCliente e tutti gli attributi del cliente. Nell'originale sostituisco NomeCliente, CognomeCliente, Via, Numero, Città, TelefonoCliente con CodiceCliente.
- EmailVenditore dipende da (NomeVenditore, CognomeVenditore) → creo la tabella Venditori con chiave primaria CodiceVenditore e tutti gli attributi del venditore. Nell'originale sostituisco NomeVenditore, CognomeVenditore, EmailVenditore con CodiceVenditore.
- La tabella originale ridotta diventa OrdiniRiformulata (CodiceOrdine, DataOrdine, CodiceCliente, CodiceVenditore).
Tabella Clienti (✅ 3NF):
| CodiceCliente | NomeCliente | CognomeCliente | Via | Numero | Città | TelefonoCliente |
| C001 | Mario | Rossi | Via Roma | 10 | Milano | 02-1234567 |
| C002 | Anna | Verdi | Via Dante | 5 | Roma | 06-7654321 |
Chiave primaria: CodiceCliente
Tabella Venditori (✅ 3NF):
Chiave primaria: CodiceVenditore
Tabella OrdiniRiformulata (✅ 3NF):
| CodiceOrdine | DataOrdine | CodiceCliente | CodiceVenditore |
| ORD001 | 2024-01-15 | C001 | V001 |
| ORD002 | 2024-01-16 | C001 | V001 |
| ORD003 | 2024-01-17 | C002 | V002 |
Chiave primaria: CodiceOrdine
Verifica 3NF per la tabella Clienti:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (CodiceCliente), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (NomeCliente, CognomeCliente, Via, Numero, Città, TelefonoCliente) dipendono direttamente dalla chiave primaria CodiceCliente. Non ci sono attributi che dipendono da altri attributi non-chiave.
Verifica 3NF per la tabella Venditori:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (CodiceVenditore), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (NomeVenditore, CognomeVenditore, EmailVenditore) dipendono direttamente dalla chiave primaria CodiceVenditore. Non ci sono attributi che dipendono da altri attributi non-chiave.
Verifica 3NF per la tabella OrdiniRiformulata:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (CodiceOrdine), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (DataOrdine, CodiceCliente, CodiceVenditore) dipendono direttamente dalla chiave primaria CodiceOrdine. CodiceCliente e CodiceVenditore sono chiavi esterne che fanno riferimento a tabelle separate.
✅
Risultato finale: Abbiamo ottenuto 5 tabelle in 3NF:
- Clienti (CodiceCliente, NomeCliente, CognomeCliente, Via, Numero, Città, TelefonoCliente)
- Venditori (CodiceVenditore, NomeVenditore, CognomeVenditore, EmailVenditore)
- Prodotti (Prodotto, PrezzoUnitario)
- OrdiniRiformulata (CodiceOrdine, DataOrdine, CodiceCliente, CodiceVenditore)
- DettagliOrdine (CodiceOrdine, Prodotto, Quantità)
Verifica: I Problemi Sono Stati Risolti?
✅ Problema di INSERIMENTO risolto:
Ora possiamo inserire un nuovo venditore nella tabella Venditori anche se non ha ancora gestito nessun ordine. Possiamo registrare un nuovo cliente anche prima che effettui un ordine.
✅ Problema di AGGIORNAMENTO risolto:
Se Mario Rossi cambia indirizzo, dobbiamo aggiornare una sola riga nella tabella Clienti. Tutti gli ordini collegati vedranno automaticamente l'indirizzo corretto tramite la chiave esterna. Nessun rischio di inconsistenza!
✅ Problema di CANCELLAZIONE risolto:
Se cancelliamo tutti gli ordini di Anna Verdi, i suoi dati anagrafici rimangono nella tabella Clienti. Non perdiamo informazioni importanti.
✅ Ridondanza eliminata:
I dati di ogni cliente appaiono una sola volta (nella tabella Clienti). I dati di ogni venditore appaiono una sola volta (nella tabella Venditori). I prezzi dei prodotti appaiono una sola volta (nella tabella Prodotti).
Riepilogo delle Forme Normali
| Forma Normale |
Requisiti |
Problemi Risolti |
| 1NF |
• Attributi atomici (no composti)
• No attributi multivalore
• Chiave primaria definita
|
• Difficoltà nelle ricerche
• Impossibilità di indicizzare correttamente
• Difficoltà nei calcoli e nelle query
|
| 2NF |
• Già in 1NF
• Assenza di attributi che dipendono da una sola parte della chiave primaria
|
• Ridondanza parziale
• Alcuni problemi di aggiornamento
|
| 3NF |
• Già in 2NF
• Assenza di attributi che dipendono da attributi non-chiave
|
• Ridondanza residua
• Tutti i problemi di inserimento, aggiornamento e cancellazione
|
Schema di Verifica Rapida
Schema Riassuntivo – Procedimento di Normalizzazione (1NF → 2NF → 3NF)
Procedimento sistematico applicato in tutti gli esercizi:
- Verifica della forma normale corrente
- Se la verifica fallisce → scomposizione in nuove tabelle
- Verifica delle nuove tabelle ottenute
- Passaggio alla forma normale successiva
📌 PASSO 1 – PRIMA FORMA NORMALE (1NF)
Condizioni da verificare:
- Attributi atomici: nessun valore composto (es. "Mario Rossi", "Via Roma 10, Milano")
- No attributi multivalore: una sola voce per cella (no liste separate da virgole o <br>)
- Chiave primaria definita: anche composta
⛔ Se NON in 1NF:
- Attributi composti: scomporre in colonne separate
- Es: "Mario Rossi" → "Nome" + "Cognome"
- Attributi multivalore: creare nuova tabella con:
- Chiave primaria della tabella originale
- Un solo valore dell'attributo multivalore per riga
✅ Risultato dopo 1NF: Tabelle con valori atomici, righe singole per valore multivalore, chiave primaria definita
📌 PASSO 2 – SECONDA FORMA NORMALE (2NF)
Condizioni da verificare (per ogni tabella):
- È già in 1NF (verificato al passo precedente)
- Assenza di dipendenze parziali: nessun attributo non-chiave dipende solo da una parte della chiave primaria (se la chiave è composta)
Nota: se la chiave primaria ha un solo attributo → 2NF automaticamente soddisfatta
⛔ Se NON in 2NF (chiave composta):
- Identificare gli attributi non-chiave che dipendono solo da una parte della chiave primaria
- Per ogni gruppo di attributi che dipendono dalla stessa parte della chiave:
- Creare una nuova tabella con:
- La parte della chiave da cui dipendono (diventa chiave primaria della nuova tabella)
- Tutti gli attributi che dipendono solo da quella parte
- Nella tabella originale mantenere solo:
- La chiave primaria originale (composta)
- Gli attributi non-chiave che dipendono dall'intera chiave
✅ Risultato dopo 2NF: Ogni attributo non-chiave dipende dall'intera chiave primaria
📌 PASSO 3 – TERZA FORMA NORMALE (3NF)
Condizioni da verificare (per ogni tabella):
- È già in 2NF (verificato al passo precedente)
- Assenza di dipendenze transitive: nessun attributo non-chiave dipende da un altro attributo non-chiave (deve dipendere direttamente dalla chiave primaria)
⛔ Se NON in 3NF:
- Identificare gli attributi non-chiave che dipendono da altri attributi non-chiave (dipendenza transitiva)
- Per ogni gruppo di attributi che dipendono da un attributo non-chiave:
- Creare una nuova tabella con:
- L'attributo non-chiave da cui dipendono gli altri (diventa chiave primaria della nuova tabella)
- Tutti gli attributi che dipendono da esso
- Nella tabella originale:
- Rimuovere gli attributi che sono stati spostati nella nuova tabella
- Mantenere l'attributo che è diventato chiave primaria nella nuova tabella come chiave esterna (se serve per la relazione)
✅ Risultato dopo 3NF: Ogni attributo non-chiave dipende direttamente e solo dalla chiave primaria
💡 Esempi Pratici dei Problemi Riscontrati
Esempi di dipendenze parziali (problema 2NF):
- Esercizio 1 (Biblioteca): "NomeAutore" dipende solo da "CodiceLibro" (parte della chiave)
- Esercizio 2 (Palestra): "Nome" dipende solo da "CodiceTessera" (parte della chiave)
- Esercizio 3 (Ristorante): "DataPrenotazione" dipende solo da "CodicePrenotazione" (parte della chiave)
Esempi di dipendenze transitive (problema 3NF):
- Esercizio 1 (Biblioteca): "NazionalitàAutore" dipende da "NomeAutore" (attributo non-chiave)
- Esercizio 2 (Palestra): "TelefonoIstruttore" dipende da "Istruttore" (attributo non-chiave)
- Esercizio 5 (Negozio): "IndirizzoFornitore" dipende da "Fornitore" (attributo non-chiave)
📊 Tabella Riassuntiva del Procedimento
| Passo |
Forma Normale |
Cosa Verificare |
Problemi Risolti |
Azione se Non Soddisfatta |
| 1 |
1NF |
1. Attributi atomici
2. No attributi multivalore
3. Chiave primaria definita
|
Struttura disordinata, difficoltà nelle query |
• Scomporre attributi composti
• Creare tabella separata per attributi multivalore
|
| 2 |
2NF |
1. Già in 1NF
2. No dipendenze parziali (se chiave composta)
|
Ridondanza parziale, aggiornamenti parziali |
• Per ogni dipendenza parziale:
- Creare tabella con parte di chiave
- Spostare attributi dipendenti
|
| 3 |
3NF |
1. Già in 2NF
2. No dipendenze transitive
|
Ridondanza residua, anomalie inserimento/aggiornamento/cancellazione |
• Per ogni dipendenza transitiva:
- Creare tabella con attributo non-chiave
- Sostituire con chiave esterna
|
🎯 Obiettivi Finali Raggiunti con 3NF:
- Eliminazione della ridondanza non necessaria
- Risoluzione delle anomalie di inserimento, aggiornamento e cancellazione
- Ogni fatto memorizzato una sola volta
- Relazioni rappresentate tramite chiavi primarie/esterne
- Struttura ottimizzata per query efficienti
Questo schema è stato applicato fedelmente in tutti e 5 gli esercizi presentati.
ESERCIZI SVOLTI
Applicazione pratica del processo di normalizzazione con verifiche dettagliate
Esercizio 1 – Gestione Biblioteca
Data la seguente tabella:
| CodiceLibro | Titolo | Genere | Autore | NazionalitàAutore |
CodiceUtente | NomeUtente | DataPrestito | Scadenza |
| L001 | Il Nome della Rosa | Giallo Storico | Umberto Eco | Italiana |
U123 | Mario Rossi | 2023-03-01 | 2023-04-01 |
| L001 | Il Nome della Rosa | Giallo Storico | Umberto Eco | Italiana |
U456 | Anna Verdi | 2023-05-15 | 2023-06-15 |
La tabella è in 3FN? Soluzione:
Passo 1 (1NF?)
Verifica 1NF per la tabella iniziale:
- Attributi atomici: ❌ Attributi composti presenti:
- "NomeUtente" contiene nome e cognome insieme
- "Autore" contiene nome e cognome insieme
- Assenza di attributi multivalore: ❌ Attributo multivalore presente:
- "Genere" contiene più valori (Giallo, Storico)
- Chiave primaria definita: ✅ (CodiceLibro, CodiceUtente, DataPrestito) può essere la chiave primaria.
Conclusione: La tabella NON è in 1NF.
Per portare la tabella in 1NF, risolvere i due problemi individuati:
- Attributi composti: "Autore" → "NomeAutore" + "CognomeAutore"; "NomeUtente" → "NomeUtente" + "CognomeUtente".
- Attributo multivalore: "Genere" viene estratto in una tabella separata formata dalla chiave primaria della tabella iniziale (CodiceLibro) e dal valore dell'attributo multivalore (Genere).
Tabella LibroPrestito (in 1NF):
| CodiceLibro | Titolo | NomeAutore | CognomeAutore |
NazionalitàAutore | CodiceUtente | NomeUtente | CognomeUtente |
DataPrestito | Scadenza |
| L001 | Il Nome della Rosa | Umberto | Eco |
Italiana | U123 | Mario | Rossi | 2023-03-01 | 2023-04-01 |
| L001 | Il Nome della Rosa | Umberto | Eco |
Italiana | U456 | Anna | Verdi | 2023-05-15 | 2023-06-15 |
Chiave primaria: (CodiceLibro, CodiceUtente, DataPrestito)
Tabella GeneriLibro (in 1NF):
| CodiceLibro | Genere |
| L001 | Giallo |
| L001 | Storico |
Chiave primaria: (CodiceLibro, Genere)
Verifica 1NF per la tabella LibroPrestito:
- Attributi atomici: ✅ Tutti gli attributi sono atomici. Gli attributi composti sono stati scomposti:
- "Autore" → "NomeAutore" + "CognomeAutore"
- "NomeUtente" → "NomeUtente" + "CognomeUtente"
- Assenza di attributi multivalore: ✅ Ogni cella contiene un solo valore. L'attributo multivalore "Genere" è stato estratto in tabella separata.
- Chiave primaria definita: ✅ (CodiceLibro, CodiceUtente, DataPrestito) è la chiave primaria e identifica univocamente ogni riga.
Verifica 1NF per la tabella GeneriLibro:
- Attributi atomici: ✅ Tutti gli attributi sono atomici (CodiceLibro, Genere).
- Assenza di attributi multivalore: ✅ Ogni cella contiene un solo valore. Il problema multivalore è risolto creando una riga separata per ogni genere di ogni libro.
- Chiave primaria definita: ✅ (CodiceLibro, Genere) è la chiave primaria e identifica univocamente ogni riga.
Conclusione: Le tabelle LibroPrestito e GeneriLibro sono ora in 1NF.
Passo 2 (2NF?)
Devo verificare la 2NF per ogni tabella ottenuta al passo precedente (LibroPrestito e GeneriLibro). Per ciascuna verifico: (1) è già in 1NF (sì, dal passo 1); (2) ogni attributo non-chiave dipende dall'intera chiave primaria e non solo da una sua parte. Se la chiave è composta da un solo attributo, la condizione (2) è automaticamente soddisfatta.
Verifica 2NF per la tabella LibroPrestito:
- Già in 1NF: ✅ Verificato nel passo precedente.
- Assenza di dipendenze parziali: ❌ La chiave primaria è composta da (CodiceLibro, CodiceUtente, DataPrestito). Ci sono attributi che dipendono solo da una parte della chiave:
- Titolo, NomeAutore, CognomeAutore, NazionalitàAutore dipendono solo da CodiceLibro
- NomeUtente, CognomeUtente dipendono solo da CodiceUtente
La tabella NON è in 2NF.
Verifica 2NF per la tabella GeneriLibro:
- Già in 1NF: ✅ Verificato nel passo precedente.
- Assenza di dipendenze parziali: ✅ Non ci sono attributi non-chiave, solo la chiave primaria (CodiceLibro, Genere). La tabella è in 2NF.
La tabella LibroPrestito non è in 2NF. Applico il seguente procedimento ad ogni parte della chiave primaria che genera dipendenze parziali : creo una nuova tabella formata da quella parte della chiave (che diventa chiave primaria della nuova tabella) più tutti gli attributi che ne dipendono. La tabella originale viene ridotta ai soli attributi che dipendono dall'intera chiave originaria, che resta invariata come sua chiave primaria. Nel nostro caso:
- Titolo, NomeAutore, CognomeAutore, NazionalitàAutore dipendono solo da CodiceLibro → creo la tabella Libro (CodiceLibro, Titolo, NomeAutore, CognomeAutore, NazionalitàAutore) con chiave primaria CodiceLibro.
- NomeUtente, CognomeUtente dipendono solo da CodiceUtente → creo la tabella Utente (CodiceUtente, NomeUtente, CognomeUtente) con chiave primaria CodiceUtente.
- Nella tabella originaria resta solo Scadenza (che dipende dall'intera chiave) → diventa la tabella Prestito (CodiceLibro, CodiceUtente, DataPrestito, Scadenza) con chiave primaria (CodiceLibro, CodiceUtente, DataPrestito).
Tabella Libro (✅ 2NF):
| CodiceLibro | Titolo | NomeAutore | CognomeAutore | NazionalitàAutore |
| L001 | Il Nome della Rosa | Umberto | Eco | Italiana |
Chiave primaria: CodiceLibro
Tabella Utente (✅ 2NF):
| CodiceUtente | NomeUtente | CognomeUtente |
| U123 | Mario | Rossi |
| U456 | Anna | Verdi |
Chiave primaria: CodiceUtente
Tabella Prestito (✅ 2NF):
| CodiceLibro | CodiceUtente | DataPrestito | Scadenza |
| L001 | U123 | 2023-03-01 | 2023-04-01 |
| L001 | U456 | 2023-05-15 | 2023-06-15 |
Chiave primaria: (CodiceLibro, CodiceUtente, DataPrestito)
Verifica 2NF per la tabella Libro:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (CodiceLibro).
- Assenza di dipendenze parziali: ✅ La chiave primaria è composta da un solo attributo (CodiceLibro), quindi la tabella è automaticamente in 2NF.
Verifica 2NF per la tabella Utente:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (CodiceUtente).
- Assenza di dipendenze parziali: ✅ La chiave primaria è composta da un solo attributo (CodiceUtente), quindi la tabella è automaticamente in 2NF.
Verifica 2NF per la tabella Prestito:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (CodiceLibro, CodiceUtente, DataPrestito).
- Assenza di dipendenze parziali: ✅ L'unico attributo non-chiave è Scadenza. Scadenza dipende dall'intera chiave (CodiceLibro, CodiceUtente, DataPrestito): la scadenza di un prestito specifico. Non ci sono attributi che dipendono solo da una parte della chiave.
Conclusione: Le 4 tabelle (Libro, Utente, Prestito, GeneriLibro) sono ora in 2NF.
Passo 3 (3NF?)
Devo verificare la 3NF per ogni tabella ottenuta al passo precedente (Libro, Utente, Prestito, GeneriLibro). Per ciascuna verifico: (1) è già in 2NF (sì, dal passo 2); (2) non ci sono attributi non-chiave che dipendono da altri attributi non-chiave (dipendenze transitive).
Verifica 3NF per la tabella Libro:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ❌ C'è una dipendenza transitiva: NazionalitàAutore dipende da (NomeAutore, CognomeAutore) che non è chiave primaria. La tabella NON è in 3NF.
Verifica 3NF per la tabella Utente:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (NomeUtente, CognomeUtente) dipendono direttamente dalla chiave primaria CodiceUtente. La tabella è in 3NF.
Verifica 3NF per la tabella Prestito:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ L'unico attributo non-chiave è Scadenza, che dipende direttamente dalla chiave primaria (CodiceLibro, CodiceUtente, DataPrestito). La tabella è in 3NF.
Verifica 3NF per la tabella GeneriLibro:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Non ci sono attributi non-chiave, solo la chiave primaria (CodiceLibro, Genere). La tabella è in 3NF.
Solo la tabella Libro non è in 3NF. Applico il seguente procedimento: per ogni dipendenza transitiva individuata, creo una nuova tabella formata dall'attributo non-chiave da cui dipendono gli altri attributi (che diventa chiave primaria della nuova tabella) più gli attributi che ne dipendono e, create le tabelle come descritto, considero la tabella originale riformulata eliminando gli attributi che dipendono da attributi non chiave. Nel nostro caso:
- NazionalitàAutore dipende da (NomeAutore, CognomeAutore) → creo la tabella Autore (NomeAutore, CognomeAutore, Nazionalità) con chiave primaria (NomeAutore, CognomeAutore).
- Dalla tabella Libro rimuovo NazionalitàAutore; NomeAutore e CognomeAutore restano come chiave esterna verso Autore → diventa LibroRiformulata (CodiceLibro, Titolo, NomeAutore, CognomeAutore).
Tabella Autore (✅ 3NF):
| NomeAutore | CognomeAutore | Nazionalità |
| Umberto | Eco | Italiana |
Chiave primaria: (NomeAutore, CognomeAutore)
Tabella LibroRiformulata (✅ 3NF):
| CodiceLibro | Titolo | NomeAutore | CognomeAutore |
| L001 | Il Nome della Rosa | Umberto | Eco |
Chiave primaria: CodiceLibro
Verifica 3NF per la tabella Autore:
- Già in 2NF: ✅ La chiave primaria è composta da (NomeAutore, CognomeAutore). L'unico attributo non-chiave è Nazionalità, che dipende dall'intera chiave, quindi la tabella è in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Nazionalità dipende direttamente dalla chiave primaria (NomeAutore, CognomeAutore). Non ci sono attributi che dipendono da altri attributi non-chiave.
Verifica 3NF per la tabella LibroRiformulata:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (CodiceLibro), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (Titolo, NomeAutore, CognomeAutore) dipendono direttamente dalla chiave primaria CodiceLibro. NomeAutore e CognomeAutore sono chiave esterna che fa riferimento alla tabella Autore.
Conclusione: Le tabelle finali in 3NF sono:
- Autore (NomeAutore, CognomeAutore, Nazionalità)
- LibroRiformulata (CodiceLibro, Titolo, NomeAutore, CognomeAutore)
- GeneriLibro (CodiceLibro, Genere)
- Utente (CodiceUtente, NomeUtente, CognomeUtente)
- Prestito (CodiceLibro, CodiceUtente, DataPrestito, Scadenza)
Esercizio 2 – Gestione Palestra
Data la seguente tabella:
| CodiceTessera | Nome | Cognome | DataIscrizione | CodiceCorso |
NomeCorso | Istruttore | TelefonoIstruttore | GiornoLezione | Orario |
| T001 | Marco | Bianchi | 2023-01-15 | C101 |
Yoga | Laura Verdi | 333-1234567 | Lunedì | 18:00 |
| T001 | Marco | Bianchi | 2023-01-15 | C102 |
Pilates | Giulia Rossi | 333-7654321 | Mercoledì | 19:00 |
La tabella è in 3FN? Soluzione corretta:
Passo 1 (1NF?)
Verifica 1NF per la tabella iniziale:
- Attributi atomici: ❌ Attributo composto presente:
- "Istruttore" contiene nome e cognome insieme (es. "Laura Verdi")
- Assenza di attributi multivalore: ✅ Ogni cella contiene un solo valore.
- Chiave primaria definita: ✅ (CodiceTessera, CodiceCorso, GiornoLezione) può essere la chiave primaria.
Conclusione: La tabella NON è in 1NF perché contiene un attributo composto.
Per portare la tabella in 1NF, scomponiamo l'attributo composto "Istruttore" in attributi atomici:
- "Istruttore" → "NomeIstruttore" + "CognomeIstruttore"
Tabella in 1NF:
| CodiceTessera | Nome | Cognome | DataIscrizione | CodiceCorso |
NomeCorso | NomeIstruttore | CognomeIstruttore | TelefonoIstruttore | GiornoLezione | Orario |
| T001 | Marco | Bianchi | 2023-01-15 | C101 |
Yoga | Laura | Verdi | 333-1234567 | Lunedì | 18:00 |
| T001 | Marco | Bianchi | 2023-01-15 | C102 |
Pilates | Giulia | Rossi | 333-7654321 | Mercoledì | 19:00 |
Chiave primaria: (CodiceTessera, CodiceCorso, GiornoLezione)
Verifica 1NF per la tabella modificata:
- Attributi atomici: ✅ Tutti gli attributi sono atomici. L'attributo composto è stato scomposto:
- "Istruttore" → "NomeIstruttore" + "CognomeIstruttore"
- Assenza di attributi multivalore: ✅ Ogni cella contiene un solo valore.
- Chiave primaria definita: ✅ (CodiceTessera, CodiceCorso, GiornoLezione) è la chiave primaria e identifica univocamente ogni riga.
Conclusione: La tabella è ora in 1NF.
Passo 2 (2NF?)
Devo verificare la 2NF per la tabella ottenuta al passo precedente (la tabella in 1NF). Verifico: (1) è già in 1NF (sì, dal passo 1); (2) ogni attributo non-chiave dipende dall'intera chiave primaria e non solo da una sua parte.
Verifica 2NF per la tabella:
- Già in 1NF: ✅ Verificato nel passo precedente.
- Assenza di dipendenze parziali: ❌ La chiave primaria è composta da (CodiceTessera, CodiceCorso, GiornoLezione). Ci sono attributi che dipendono solo da una parte della chiave:
- Nome, Cognome, DataIscrizione dipendono solo da CodiceTessera
- NomeCorso, NomeIstruttore, CognomeIstruttore, TelefonoIstruttore dipendono solo da CodiceCorso
La tabella NON è in 2NF.
La tabella non è in 2NF. Applico il procedimento: per ogni parte della chiave primaria che genera dipendenze parziali, creo una nuova tabella formata da quella parte della chiave (che diventa chiave primaria della nuova tabella) più tutti gli attributi che ne dipendono. La tabella originale viene ridotta ai soli attributi che dipendono dall'intera chiave originaria. Nel nostro caso:
- Nome, Cognome, DataIscrizione dipendono solo da CodiceTessera → creo la tabella Clienti (CodiceTessera, Nome, Cognome, DataIscrizione) con chiave primaria CodiceTessera.
- NomeCorso, NomeIstruttore, CognomeIstruttore, TelefonoIstruttore dipendono solo da CodiceCorso → creo la tabella Corsi (CodiceCorso, NomeCorso, NomeIstruttore, CognomeIstruttore, TelefonoIstruttore) con chiave primaria CodiceCorso.
- Nella tabella originaria resta solo Orario (che dipende dall'intera chiave) → diventa la tabella Prenotazioni (CodiceTessera, CodiceCorso, GiornoLezione, Orario) con chiave primaria (CodiceTessera, CodiceCorso, GiornoLezione).
Tabella Clienti (✅ 2NF):
| CodiceTessera | Nome | Cognome | DataIscrizione |
| T001 | Marco | Bianchi | 2023-01-15 |
Chiave primaria: CodiceTessera
Tabella Corsi (✅ 2NF):
| CodiceCorso | NomeCorso | NomeIstruttore | CognomeIstruttore | TelefonoIstruttore |
| C101 | Yoga | Laura | Verdi | 333-1234567 |
| C102 | Pilates | Giulia | Rossi | 333-7654321 |
Chiave primaria: CodiceCorso
Tabella Prenotazioni (✅ 2NF):
| CodiceTessera | CodiceCorso | GiornoLezione | Orario |
| T001 | C101 | Lunedì | 18:00 |
| T001 | C102 | Mercoledì | 19:00 |
Chiave primaria: (CodiceTessera, CodiceCorso, GiornoLezione)
Verifica 2NF per la tabella Clienti:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (CodiceTessera).
- Assenza di dipendenze parziali: ✅ La chiave primaria è composta da un solo attributo (CodiceTessera), quindi la tabella è automaticamente in 2NF.
Verifica 2NF per la tabella Corsi:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (CodiceCorso).
- Assenza di dipendenze parziali: ✅ La chiave primaria è composta da un solo attributo (CodiceCorso), quindi la tabella è automaticamente in 2NF.
Verifica 2NF per la tabella Prenotazioni:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (CodiceTessera, CodiceCorso, GiornoLezione).
- Assenza di dipendenze parziali: ✅ L'unico attributo non-chiave è Orario. Orario dipende dall'intera chiave (CodiceTessera, CodiceCorso, GiornoLezione): l'orario di una lezione specifica per un cliente specifico. Non ci sono attributi che dipendono solo da una parte della chiave.
Conclusione: Le tabelle Clienti, Corsi e Prenotazioni sono ora in 2NF.
Passo 3 (3NF?)
Devo verificare la 3NF per ogni tabella ottenuta al passo precedente (Clienti, Corsi, Prenotazioni). Per ciascuna verifico: (1) è già in 2NF (sì, dal passo 2); (2) non ci sono attributi non-chiave che dipendono da altri attributi non-chiave.
Verifica 3NF per la tabella Clienti:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (Nome, Cognome, DataIscrizione) dipendono direttamente dalla chiave primaria CodiceTessera. La tabella è in 3NF.
Verifica 3NF per la tabella Corsi:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ❌ C'è una dipendenza transitiva: NomeIstruttore e CognomeIstruttore dipendono da TelefonoIstruttore (attributo non-chiave). La tabella NON è in 3NF.
Verifica 3NF per la tabella Prenotazioni:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ L'unico attributo non-chiave è Orario, che dipende direttamente dalla chiave primaria (CodiceTessera, CodiceCorso, GiornoLezione). La tabella è in 3NF.
Solo la tabella Corsi non è in 3NF. Applico il procedimento: per ogni dipendenza transitiva individuata, creo una nuova tabella formata dall'attributo non-chiave da cui dipendono gli altri attributi (che diventa chiave primaria della nuova tabella) più gli attributi che ne dipendono. La tabella originale viene ridotta eliminando gli attributi che dipendono da attributi non-chiave. Nel nostro caso:
- NomeIstruttore e CognomeIstruttore dipendono da TelefonoIstruttore (attributo non-chiave) → creo la tabella Istruttori (TelefonoIstruttore, NomeIstruttore, CognomeIstruttore) con chiave primaria TelefonoIstruttore.
- Dalla tabella Corsi rimuovo NomeIstruttore e CognomeIstruttore; TelefonoIstruttore resta come chiave esterna verso Istruttori → diventa CorsiRiformulata (CodiceCorso, NomeCorso, TelefonoIstruttore).
Tabella Istruttori (✅ 3NF):
| TelefonoIstruttore | NomeIstruttore | CognomeIstruttore |
| 333-1234567 | Laura | Verdi |
| 333-7654321 | Giulia | Rossi |
Chiave primaria: TelefonoIstruttore
Tabella CorsiRiformulata (✅ 3NF):
| CodiceCorso | NomeCorso | TelefonoIstruttore |
| C101 | Yoga | 333-1234567 |
| C102 | Pilates | 333-7654321 |
Chiave primaria: CodiceCorso
Verifica 3NF per la tabella Istruttori:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (TelefonoIstruttore), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (NomeIstruttore, CognomeIstruttore) dipendono direttamente dalla chiave primaria TelefonoIstruttore. Non ci sono attributi che dipendono da altri attributi non-chiave.
Verifica 3NF per la tabella CorsiRiformulata:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (CodiceCorso), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (NomeCorso, TelefonoIstruttore) dipendono direttamente dalla chiave primaria CodiceCorso. TelefonoIstruttore è chiave esterna che fa riferimento alla tabella Istruttori.
Conclusione: Le tabelle finali in 3NF sono:
- Clienti (CodiceTessera, Nome, Cognome, DataIscrizione)
- Istruttori (TelefonoIstruttore, NomeIstruttore, CognomeIstruttore)
- CorsiRiformulata (CodiceCorso, NomeCorso, TelefonoIstruttore)
- Prenotazioni (CodiceTessera, CodiceCorso, GiornoLezione, Orario)
Esercizio 3 – Gestione Ristorante
Data la seguente tabella:
| CodicePrenotazione | DataPrenotazione | NomeCliente | TelefonoCliente |
CodiceTavolo | PostiTavolo | MenuScelto | PrezzoMenu |
| PR001 | 2023-10-10 | Mario Rossi | 339-1234567 |
T01 | 4 | Menu Vegetariano | 25.00 |
| PR002 | 2023-10-11 | Anna Verdi | 338-7654321 |
T02 | 2 | Menu Carnivoro | 30.00 |
La tabella è in 3FN? Soluzione:
Passo 1 (1NF?)
Verifica 1NF per la tabella iniziale:
- Attributi atomici: ❌ Attributo composto presente:
- "NomeCliente" contiene nome e cognome insieme
- Assenza di attributi multivalore: ✅ Ogni cella contiene un solo valore.
- Chiave primaria definita: ✅ (CodicePrenotazione, CodiceTavolo) può essere la chiave primaria.
Conclusione: La tabella NON è in 1NF.
Per portare la tabella in 1NF, scomponiamo l'attributo composto "NomeCliente" in attributi atomici:
Tabella in 1NF:
| CodicePrenotazione | DataPrenotazione | Nome | Cognome |
TelefonoCliente | CodiceTavolo | PostiTavolo | MenuScelto | PrezzoMenu |
| PR001 | 2023-10-10 | Mario | Rossi | 339-1234567 |
T01 | 4 | Menu Vegetariano | 25.00 |
| PR002 | 2023-10-11 | Anna | Verdi | 338-7654321 |
T02 | 2 | Menu Carnivoro | 30.00 |
Chiave primaria: (CodicePrenotazione, CodiceTavolo)
Verifica 1NF per la tabella modificata:
- Attributi atomici: ✅ Tutti gli attributi sono atomici. L'attributo composto è stato scomposto:
- "NomeCliente" → "Nome" + "Cognome"
- Assenza di attributi multivalore: ✅ Ogni cella contiene un solo valore.
- Chiave primaria definita: ✅ (CodicePrenotazione, CodiceTavolo) è la chiave primaria e identifica univocamente ogni riga.
Conclusione: La tabella è ora in 1NF.
Passo 2 (2NF?)
Devo verificare la 2NF per la tabella ottenuta al passo precedente (la tabella in 1NF). Verifico: (1) è già in 1NF (sì, dal passo 1); (2) ogni attributo non-chiave dipende dall'intera chiave primaria e non solo da una sua parte.
Verifica 2NF per la tabella:
- Già in 1NF: ✅ Verificato nel passo precedente.
- Assenza di dipendenze parziali: ❌ La chiave primaria è composta da (CodicePrenotazione, CodiceTavolo). Ci sono attributi che dipendono solo da una parte della chiave:
- DataPrenotazione, Nome, Cognome, TelefonoCliente, MenuScelto, PrezzoMenu dipendono solo da CodicePrenotazione
- PostiTavolo dipende solo da CodiceTavolo
La tabella NON è in 2NF.
La tabella non è in 2NF. Applico il seguente procedimento ad ogni parte della chiave primaria che genera dipendenze parziali : creo una nuova tabella formata da quella parte della chiave (che diventa chiave primaria della nuova tabella) più tutti gli attributi che ne dipendono. La tabella originale viene ridotta ai soli attributi che dipendono dall'intera chiave originaria. Nel nostro caso:
- DataPrenotazione, Nome, Cognome, TelefonoCliente, MenuScelto, PrezzoMenu dipendono solo da CodicePrenotazione → creo la tabella Prenotazione (CodicePrenotazione, DataPrenotazione, Nome, Cognome, TelefonoCliente, MenuScelto, PrezzoMenu) con chiave primaria CodicePrenotazione.
- PostiTavolo dipende solo da CodiceTavolo → creo la tabella Tavoli (CodiceTavolo, PostiTavolo) con chiave primaria CodiceTavolo.
- Nella tabella originaria non resta alcun attributo oltre alle parti della chiave → diventa la tabella Assegnazione (CodicePrenotazione, CodiceTavolo) con chiave primaria (CodicePrenotazione, CodiceTavolo).
Tabella Prenotazione (✅ 2NF):
| CodicePrenotazione | DataPrenotazione | Nome | Cognome |
TelefonoCliente | MenuScelto | PrezzoMenu |
| PR001 | 2023-10-10 | Mario | Rossi | 339-1234567 | Menu Vegetariano | 25.00 |
| PR002 | 2023-10-11 | Anna | Verdi | 338-7654321 | Menu Carnivoro | 30.00 |
Chiave primaria: CodicePrenotazione
Tabella Tavoli (✅ 2NF):
| CodiceTavolo | PostiTavolo |
| T01 | 4 |
| T02 | 2 |
Chiave primaria: CodiceTavolo
Tabella Assegnazione (✅ 2NF):
| CodicePrenotazione | CodiceTavolo |
| PR001 | T01 |
| PR002 | T02 |
Chiave primaria: (CodicePrenotazione, CodiceTavolo)
Verifica 2NF per la tabella Prenotazione:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (CodicePrenotazione).
- Assenza di dipendenze parziali: ✅ La chiave primaria è composta da un solo attributo (CodicePrenotazione), quindi la tabella è automaticamente in 2NF.
Verifica 2NF per la tabella Tavoli:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (CodiceTavolo).
- Assenza di dipendenze parziali: ✅ La chiave primaria è composta da un solo attributo (CodiceTavolo), quindi la tabella è automaticamente in 2NF.
Verifica 2NF per la tabella Assegnazione:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (CodicePrenotazione, CodiceTavolo).
- Assenza di dipendenze parziali: ✅ Non ci sono attributi non-chiave, solo la chiave primaria (CodicePrenotazione, CodiceTavolo). La tabella è in 2NF.
Conclusione: Le tabelle Prenotazione, Tavoli e Assegnazione sono ora in 2NF.
Passo 3 (3NF?)
Devo verificare la 3NF per ogni tabella ottenuta al passo precedente (Prenotazione, Tavoli, Assegnazione). Per ciascuna verifico: (1) è già in 2NF (sì, dal passo 2); (2) non ci sono attributi non-chiave che dipendono da altri attributi non-chiave.
Verifica 3NF per la tabella Prenotazione:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ❌ Ci sono attributi che dipendono da attributi che non sono chiave primaria:
- Nome e Cognome dipendono da TelefonoCliente (che identifica univocamente il cliente) e non dalla chiave primaria della prenotazione.
La tabella NON è in 3NF.
Verifica 3NF per la tabella Tavoli:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ L'unico attributo non-chiave è PostiTavolo, che dipende direttamente dalla chiave primaria CodiceTavolo. La tabella è in 3NF.
Verifica 3NF per la tabella Assegnazione:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Non ci sono attributi non-chiave, solo la chiave primaria (CodicePrenotazione, CodiceTavolo). La tabella è in 3NF.
Solo la tabella Prenotazione non è in 3NF. Applico il seguente procedimento: per ogni dipendenza transitiva individuata, creo una nuova tabella formata dall'attributo non-chiave da cui dipendono gli altri attributi (che diventa chiave primaria della nuova tabella) più gli attributi che ne dipendono e, create le tabelle come descritto, considero la tabella originale riformulata eliminando gli attributi che dipendono da attributi non chiave. Nel nostro caso:
- Nome e Cognome dipendono da TelefonoCliente → creo la tabella Cliente (TelefonoCliente, Nome, Cognome) con chiave primaria TelefonoCliente.
- PrezzoMenu dipende da MenuScelto → creo la tabella Menu (MenuScelto, PrezzoMenu) con chiave primaria MenuScelto.
- Dalla tabella Prenotazione rimuovo Nome, Cognome e PrezzoMenu; TelefonoCliente e MenuScelto restano come chiavi esterne → diventa PrenotazioneRiformulata (CodicePrenotazione, DataPrenotazione, TelefonoCliente, MenuScelto).
Tabella Cliente (✅ 3NF):
| TelefonoCliente | Nome | Cognome |
| 339-1234567 | Mario | Rossi |
| 338-7654321 | Anna | Verdi |
Chiave primaria: TelefonoCliente
Tabella Menu (✅ 3NF):
| MenuScelto | PrezzoMenu |
| Menu Vegetariano | 25.00 |
| Menu Carnivoro | 30.00 |
Chiave primaria: MenuScelto
Tabella PrenotazioneRiformulata (✅ 3NF):
| CodicePrenotazione | DataPrenotazione | TelefonoCliente | MenuScelto |
| PR001 | 2023-10-10 | 339-1234567 | Menu Vegetariano |
| PR002 | 2023-10-11 | 338-7654321 | Menu Carnivoro |
Chiave primaria: CodicePrenotazione
Verifica 3NF per la tabella Cliente:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (TelefonoCliente), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (Nome, Cognome) dipendono direttamente dalla chiave primaria TelefonoCliente.
Verifica 3NF per la tabella Menu:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (MenuScelto), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ L'unico attributo non-chiave è PrezzoMenu, che dipende direttamente dalla chiave primaria MenuScelto.
Verifica 3NF per la tabella PrenotazioneRiformulata:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (CodicePrenotazione), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (DataPrenotazione, TelefonoCliente, MenuScelto) dipendono direttamente dalla chiave primaria CodicePrenotazione. TelefonoCliente e MenuScelto sono chiavi esterne che fanno riferimento alle tabelle Cliente e Menu.
Conclusione: Le tabelle sono ora in 3NF.
Esercizio 4 – Gestione Università
Data la seguente tabella:
| Matricola | Nome | Cognome | Corso | Docente | Dipartimento |
| M001 | Mario | Rossi | DB | Prof. Bianchi | Informatica |
| M001 | Mario | Rossi | AI | Prof. Verdi | Informatica |
| M002 | Anna | Verdi | DB | Prof. Bianchi | Informatica |
La tabella è in 3FN? Soluzione:
Passo 1 (1NF?)
Verifica 1NF per la tabella iniziale:
- Attributi atomici: ✅ Tutti gli attributi sono atomici.
- Assenza di attributi multivalore: ✅ Ogni cella contiene un solo valore.
- Chiave primaria definita: ✅ (Matricola, Corso) può essere la chiave primaria.
Conclusione: La tabella è già in 1NF.
Conclusione: La tabella è già in 1NF.
Passo 2 (2NF?)
Devo verificare la 2NF per la tabella ottenuta al passo precedente (la tabella iniziale, già in 1NF). Verifico: (1) è già in 1NF (sì, dal passo 1); (2) ogni attributo non-chiave dipende dall'intera chiave primaria e non solo da una sua parte.
Verifica 2NF per la tabella:
- Già in 1NF: ✅ Verificato nel passo precedente.
- Assenza di dipendenze parziali: ❌ La chiave primaria è composta da (Matricola, Corso). Ci sono attributi che dipendono solo da una parte della chiave:
- Nome, Cognome dipendono solo da Matricola
- Docente, Dipartimento dipendono solo da Corso
La tabella NON è in 2NF.
La tabella non è in 2NF. Applico il seguente procedimento ad ogni parte della chiave primaria che genera dipendenze parziali : creo una nuova tabella formata da quella parte della chiave (che diventa chiave primaria della nuova tabella) più tutti gli attributi che ne dipendono. La tabella originale viene ridotta ai soli attributi che dipendono dall'intera chiave originaria. Nel nostro caso:
- Nome, Cognome dipendono solo da Matricola → creo la tabella Studenti (Matricola, Nome, Cognome) con chiave primaria Matricola.
- Docente, Dipartimento dipendono solo da Corso → creo la tabella Corsi (Corso, Docente, Dipartimento) con chiave primaria Corso.
- Nella tabella originaria non resta alcun attributo oltre alle parti della chiave → diventa la tabella Iscrizioni (Matricola, Corso) con chiave primaria (Matricola, Corso).
Tabella Studenti (✅ 2NF):
| Matricola | Nome | Cognome |
| M001 | Mario | Rossi |
| M002 | Anna | Verdi |
Chiave primaria: Matricola
Tabella Corsi (✅ 2NF):
| Corso | Docente | Dipartimento |
| DB | Prof. Bianchi | Informatica |
| AI | Prof. Verdi | Informatica |
Chiave primaria: Corso
Tabella Iscrizioni (✅ 2NF):
| Matricola | Corso |
| M001 | DB |
| M001 | AI |
| M002 | DB |
Chiave primaria: (Matricola, Corso)
Verifica 2NF per la tabella Studenti:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (Matricola).
- Assenza di dipendenze parziali: ✅ La chiave primaria è composta da un solo attributo (Matricola), quindi la tabella è automaticamente in 2NF.
Verifica 2NF per la tabella Corsi:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (Corso).
- Assenza di dipendenze parziali: ✅ La chiave primaria è composta da un solo attributo (Corso), quindi la tabella è automaticamente in 2NF.
Verifica 2NF per la tabella Iscrizioni:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (Matricola, Corso).
- Assenza di dipendenze parziali: ✅ Non ci sono attributi non-chiave, solo la chiave primaria (Matricola, Corso). La tabella è in 2NF.
Conclusione: Le tabelle Studenti, Corsi e Iscrizioni sono ora in 2NF.
Passo 3 (3NF?)
Devo verificare la 3NF per ogni tabella ottenuta al passo precedente (Studenti, Corsi, Iscrizioni). Per ciascuna verifico: (1) è già in 2NF (sì, dal passo 2); (2) non ci sono attributi non-chiave che dipendono da altri attributi non-chiave.
Verifica 3NF per la tabella Studenti:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (Nome, Cognome) dipendono direttamente dalla chiave primaria Matricola. La tabella è in 3NF.
Verifica 3NF per la tabella Corsi:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ❌ C'è una dipendenza transitiva: Dipartimento dipende da Docente, che non è chiave primaria. La tabella NON è in 3NF.
Verifica 3NF per la tabella Iscrizioni:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Non ci sono attributi non-chiave, solo la chiave primaria (Matricola, Corso). La tabella è in 3NF.
Solo la tabella Corsi non è in 3NF. Applico il seguente procedimento: per ogni dipendenza transitiva individuata, creo una nuova tabella formata dall'attributo non-chiave da cui dipendono gli altri attributi (che diventa chiave primaria della nuova tabella) più gli attributi che ne dipendono e, create le tabelle come descritto, considero la tabella originale riformulata eliminando gli attributi che dipendono da attributi non chiave. Nel nostro caso:
- Dipartimento dipende da Docente → creo la tabella Docenti (Docente, Dipartimento) con chiave primaria Docente.
- Dalla tabella Corsi rimuovo Dipartimento; Docente resta come chiave esterna verso Docenti → diventa CorsiRiformulata (Corso, Docente).
Tabella Docenti (✅ 3NF):
| Docente | Dipartimento |
| Prof. Bianchi | Informatica |
| Prof. Verdi | Informatica |
Chiave primaria: Docente
Tabella CorsiRiformulata (✅ 3NF):
| Corso | Docente |
| DB | Prof. Bianchi |
| AI | Prof. Verdi |
Chiave primaria: Corso
Verifica 3NF per la tabella Docenti:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (Docente), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ L'unico attributo non-chiave è Dipartimento, che dipende direttamente dalla chiave primaria Docente.
Verifica 3NF per la tabella CorsiRiformulata:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (Corso), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ L'unico attributo non-chiave è Docente, che dipende direttamente dalla chiave primaria Corso. Docente è chiave esterna che fa riferimento alla tabella Docenti.
Conclusione: Le tabelle sono ora in 3NF.
Esercizio 5 – Gestione Negozio
Data la seguente tabella:
| CodiceProdotto | NomeProdotto | Fornitore | IndirizzoFornitore | Prezzo | Categoria |
| P001 | Laptop | TechCorp | Roma | 1200 | Elettronica |
| P002 | Mouse | TechCorp | Roma | 25 | Elettronica |
| P003 | Tastiera | OfficeSup | Milano | 50 | Ufficio |
La tabella è in 3FN? Soluzione:
Passo 1 (1NF?)
Verifica 1NF per la tabella iniziale:
- Attributi atomici: ✅ Tutti gli attributi sono atomici.
- Assenza di attributi multivalore: ✅ Ogni cella contiene un solo valore.
- Chiave primaria definita: ✅ CodiceProdotto può essere la chiave primaria.
Conclusione: La tabella è già in 1NF.
Conclusione: La tabella è già in 1NF.
Passo 2 (2NF?)
Devo verificare la 2NF per la tabella ottenuta al passo precedente (la tabella iniziale, già in 1NF). Verifico: (1) è già in 1NF (sì, dal passo 1); (2) ogni attributo non-chiave dipende dall'intera chiave primaria e non solo da una sua parte. Se la chiave è composta da un solo attributo, la condizione (2) è automaticamente soddisfatta.
Verifica 2NF per la tabella:
- Già in 1NF: ✅ Verificato nel passo precedente.
- Assenza di dipendenze parziali: ✅ La chiave primaria è composta da un solo attributo (CodiceProdotto), quindi per definizione non ci possono essere attributi che dipendono da una sola parte della chiave primaria. La tabella è automaticamente in 2NF.
Conclusione: La tabella è già in 2NF.
Passo 3 (3NF?)
Devo verificare la 3NF per la tabella ottenuta al passo precedente (la tabella, già in 2NF). Verifico: (1) è già in 2NF (sì, dal passo 2); (2) non ci sono attributi non-chiave che dipendono da altri attributi non-chiave.
Verifica 3NF per la tabella:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ❌ C'è una dipendenza transitiva: IndirizzoFornitore dipende da Fornitore, che non è chiave primaria. La tabella NON è in 3NF.
La tabella non è in 3NF. Applico il seguente procedimento: per ogni dipendenza transitiva individuata, creo una nuova tabella formata dall'attributo non-chiave da cui dipendono gli altri attributi (che diventa chiave primaria della nuova tabella) più gli attributi che ne dipendono e, create le tabelle come descritto, considero la tabella originale riformulata eliminando gli attributi che dipendono da attributi non chiave. Nel nostro caso:
- IndirizzoFornitore dipende da Fornitore → creo la tabella Fornitori (Fornitore, IndirizzoFornitore) con chiave primaria Fornitore.
- Dalla tabella originale rimuovo IndirizzoFornitore; Fornitore resta come chiave esterna verso Fornitori → diventa ProdottiRiformulata (CodiceProdotto, NomeProdotto, Fornitore, Prezzo, Categoria).
Tabella Fornitori (✅ 3NF):
| Fornitore | IndirizzoFornitore |
| TechCorp | Roma |
| OfficeSup | Milano |
Chiave primaria: Fornitore
Tabella ProdottiRiformulata (✅ 3NF):
| CodiceProdotto | NomeProdotto | Fornitore | Prezzo | Categoria |
| P001 | Laptop | TechCorp | 1200 | Elettronica |
| P002 | Mouse | TechCorp | 25 | Elettronica |
| P003 | Tastiera | OfficeSup | 50 | Ufficio |
Chiave primaria: CodiceProdotto
Verifica 3NF per la tabella Fornitori:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (Fornitore), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ L'unico attributo non-chiave è IndirizzoFornitore, che dipende direttamente dalla chiave primaria Fornitore. Non ci sono attributi che dipendono da altri attributi non-chiave.
Verifica 3NF per la tabella ProdottiRiformulata:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (CodiceProdotto), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (NomeProdotto, Fornitore, Prezzo, Categoria) dipendono direttamente dalla chiave primaria CodiceProdotto. Fornitore è chiave esterna che fa riferimento alla tabella Fornitori.
Conclusione: Le tabelle sono ora in 3NF.
Esercizi Aggiuntivi di Normalizzazione Database
Tre nuovi esercizi completi con soluzioni dettagliate seguendo lo stesso schema risolutivo dei precedenti.
Ogni esercizio applica rigorosamente il procedimento: 1NF → 2NF → 3NF con verifiche passo-passo.
Esercizio 6 – Gestione Prenotazioni Hotel
Un hotel gestisce le prenotazioni dei clienti. La seguente tabella contiene tutte le informazioni:
| CodicePrenotazione | DataCheckIn | DataCheckOut | NomeCliente | CognomeCliente |
TelefonoCliente | TipoCamera | PrezzoCamera | ServiziAggiuntivi | CostoServizi |
| PR001 | 2024-06-10 | 2024-06-15 | Mario | Rossi |
339-1234567 | Suite | 200 | Colazione Parcheggio | 30 20 |
| PR002 | 2024-06-12 | 2024-06-14 | Anna | Verdi |
338-7654321 | Standard | 100 | Colazione | 30 |
| PR003 | 2024-06-15 | 2024-06-20 | Mario | Rossi |
339-1234567 | Suite | 200 | Spa | 50 |
La tabella è in 3FN? Soluzione:
Passo 1 (1NF?)
Verifica 1NF per la tabella iniziale:
- Attributi atomici: ✅ Tutti gli attributi sono atomici.
- Assenza di attributi multivalore: ❌ Attributi multivalore presenti:
- "ServiziAggiuntivi" contiene più valori (es. "Colazione, Parcheggio")
- "CostoServizi" contiene più valori corrispondenti ai servizi
- Chiave primaria definita: ✅ CodicePrenotazione può essere la chiave primaria.
Conclusione: La tabella NON è in 1NF a causa degli attributi multivalore.
Trasformazione in 1NF: Creare una tabella separata per gli attributi multivalore "ServiziAggiuntivi" e "CostoServizi".
Tabella Prenotazioni (in 1NF):
| CodicePrenotazione | DataCheckIn | DataCheckOut | NomeCliente | CognomeCliente |
TelefonoCliente | TipoCamera | PrezzoCamera |
| PR001 | 2024-06-10 | 2024-06-15 | Mario | Rossi |
339-1234567 | Suite | 200 |
| PR002 | 2024-06-12 | 2024-06-14 | Anna | Verdi |
338-7654321 | Standard | 100 |
| PR003 | 2024-06-15 | 2024-06-20 | Mario | Rossi |
339-1234567 | Suite | 200 |
Chiave primaria: CodicePrenotazione
Tabella ServiziPrenotazione (in 1NF):
| CodicePrenotazione | Servizio | Costo |
| PR001 | Colazione | 30 |
| PR001 | Parcheggio | 20 |
| PR002 | Colazione | 30 |
| PR003 | Spa | 50 |
Chiave primaria: (CodicePrenotazione, Servizio)
Verifica 1NF per la tabella Prenotazioni:
- Attributi atomici: ✅ Tutti gli attributi sono atomici (CodicePrenotazione, DataCheckIn, DataCheckOut, NomeCliente, CognomeCliente, TelefonoCliente, TipoCamera, PrezzoCamera).
- Assenza di attributi multivalore: ✅ Gli attributi multivalore ServiziAggiuntivi e CostoServizi sono stati estratti nella tabella ServiziPrenotazione. Ogni cella contiene un solo valore.
- Chiave primaria definita: ✅ CodicePrenotazione è la chiave primaria e identifica univocamente ogni riga.
Verifica 1NF per la tabella ServiziPrenotazione:
- Attributi atomici: ✅ Tutti gli attributi sono atomici (CodicePrenotazione, Servizio, Costo).
- Assenza di attributi multivalore: ✅ Il problema multivalore è risolto creando una riga separata per ogni servizio di ogni prenotazione.
- Chiave primaria definita: ✅ (CodicePrenotazione, Servizio) è la chiave primaria e identifica univocamente ogni riga.
Conclusione: Le tabelle Prenotazioni e ServiziPrenotazione sono ora in 1NF.
Passo 2 (2NF?)
Devo verificare la 2NF per ogni tabella ottenuta al passo precedente (Prenotazioni e ServiziPrenotazione). Per ciascuna verifico: (1) è già in 1NF (sì, dal passo 1); (2) ogni attributo non-chiave dipende dall'intera chiave primaria e non solo da una sua parte. Se la chiave è composta da un solo attributo, la condizione (2) è automaticamente soddisfatta.
Verifica 2NF per Prenotazioni:
- Già in 1NF: ✅ Verificato nel passo precedente.
- Assenza di dipendenze parziali: ✅ La chiave primaria è composta da un solo attributo (CodicePrenotazione), quindi la tabella è automaticamente in 2NF.
Verifica 2NF per ServiziPrenotazione:
- Già in 1NF: ✅ Verificato nel passo precedente.
- Assenza di dipendenze parziali: ✅ La chiave è (CodicePrenotazione, Servizio). L'attributo non-chiave Costo dipende dall'intera chiave (il costo di un servizio specifico in una prenotazione specifica). Non ci sono attributi che dipendono solo da una parte della chiave.
Conclusione: Entrambe le tabelle sono in 2NF.
Passo 3 (3NF?)
Devo verificare la 3NF per ogni tabella ottenuta al passo precedente (Prenotazioni e ServiziPrenotazione). Per ciascuna verifico: (1) è già in 2NF (sì, dal passo 2); (2) non ci sono attributi non-chiave che dipendono da altri attributi non-chiave (dipendenze transitive).
Verifica 3NF per Prenotazioni:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ❌ Ci sono dipendenze transitive:
- NomeCliente e CognomeCliente dipendono da TelefonoCliente (attributo non-chiave che identifica il cliente)
- PrezzoCamera dipende da TipoCamera che non è chiave primaria
La tabella NON è in 3NF.
Verifica 3NF per ServiziPrenotazione:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ L'unico attributo non-chiave è Costo, che dipende direttamente dalla chiave primaria (CodicePrenotazione, Servizio). La tabella è in 3NF.
Solo la tabella Prenotazioni non è in 3NF. Applico il seguente procedimento: per ogni dipendenza transitiva individuata, creo una nuova tabella formata dall'attributo non-chiave da cui dipendono gli altri attributi (che diventa chiave primaria della nuova tabella) più gli attributi che ne dipendono e, create le tabelle come descritto, considero la tabella originale riformulata eliminando gli attributi che dipendono da attributi non chiave. Nel nostro caso:
- TelefonoCliente dipende da (NomeCliente, CognomeCliente) → creo la tabella Clienti (TelefonoCliente, NomeCliente, CognomeCliente) con chiave primaria TelefonoCliente.
- PrezzoCamera dipende da TipoCamera → creo la tabella Camere (TipoCamera, PrezzoCamera) con chiave primaria TipoCamera.
- Dalla tabella Prenotazioni rimuovo NomeCliente, CognomeCliente e PrezzoCamera; TelefonoCliente e TipoCamera restano come chiavi esterne → diventa PrenotazioniRiformulata (CodicePrenotazione, DataCheckIn, DataCheckOut, TelefonoCliente, TipoCamera).
Trasformazione in 3NF: Scomporre la tabella Prenotazioni eliminando le dipendenze transitive.
Tabella Clienti (✅ 3NF):
| TelefonoCliente | NomeCliente | CognomeCliente |
| 339-1234567 | Mario | Rossi |
| 338-7654321 | Anna | Verdi |
Chiave primaria: TelefonoCliente
Tabella Camere (✅ 3NF):
| TipoCamera | PrezzoCamera |
| Suite | 200 |
| Standard | 100 |
Chiave primaria: TipoCamera
Tabella PrenotazioniRiformulata (✅ 3NF):
| CodicePrenotazione | DataCheckIn | DataCheckOut | TelefonoCliente | TipoCamera |
| PR001 | 2024-06-10 | 2024-06-15 | 339-1234567 | Suite |
| PR002 | 2024-06-12 | 2024-06-14 | 338-7654321 | Standard |
| PR003 | 2024-06-15 | 2024-06-20 | 339-1234567 | Suite |
Chiave primaria: CodicePrenotazione
Verifica 3NF per la tabella Clienti:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (TelefonoCliente), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (NomeCliente, CognomeCliente) dipendono direttamente dalla chiave primaria TelefonoCliente. Non ci sono attributi che dipendono da altri attributi non-chiave.
Verifica 3NF per la tabella Camere:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (TipoCamera), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ L'unico attributo non-chiave è PrezzoCamera, che dipende direttamente dalla chiave primaria TipoCamera. Non ci sono attributi che dipendono da altri attributi non-chiave.
Verifica 3NF per la tabella PrenotazioniRiformulata:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (CodicePrenotazione), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (DataCheckIn, DataCheckOut, TelefonoCliente, TipoCamera) dipendono direttamente dalla chiave primaria CodicePrenotazione. TelefonoCliente e TipoCamera sono chiavi esterne che fanno riferimento alle tabelle Clienti e Camere.
Verifica 3NF per la tabella ServiziPrenotazione:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ L'unico attributo non-chiave è Costo, che dipende direttamente dalla chiave primaria (CodicePrenotazione, Servizio). La tabella è in 3NF.
Conclusione: Le tabelle finali in 3NF sono:
- Clienti (TelefonoCliente, NomeCliente, CognomeCliente)
- Camere (TipoCamera, PrezzoCamera)
- PrenotazioniRiformulata (CodicePrenotazione, DataCheckIn, DataCheckOut, TelefonoCliente, TipoCamera)
- ServiziPrenotazione (CodicePrenotazione, Servizio, Costo)
Esercizio 7 – Gestione Progetti Aziendali
Un'azienda gestisce progetti e le risorse assegnate. La seguente tabella contiene tutte le informazioni:
| CodiceProgetto | NomeProgetto | Budget | Responsabile | EmailResponsabile |
CodiceDipendente | NomeDipendente | Ruolo | OreAssegnate | TariffaOraria |
| PJ001 | Sistema CRM | 50000 | Marco Bianchi | [email protected] |
D101 | Laura Rossi | Sviluppatore | 120 | 40 |
| PJ001 | Sistema CRM | 50000 | Marco Bianchi | [email protected] |
D102 | Giuseppe Verdi | Analista | 80 | 50 |
| PJ002 | App Mobile | 30000 | Anna Neri | [email protected] |
D101 | Laura Rossi | Sviluppatore | 200 | 40 |
La tabella è in 3FN? Soluzione:
Passo 1 (1NF?)
Verifica 1NF per la tabella iniziale:
- Attributi atomici: ❌ Attributi composti presenti:
- "Responsabile" contiene nome e cognome insieme (es. "Marco Bianchi")
- "NomeDipendente" contiene nome e cognome insieme (es. "Laura Rossi")
- Assenza di attributi multivalore: ✅ Ogni cella contiene un solo valore.
- Chiave primaria definita: ✅ (CodiceProgetto, CodiceDipendente) può essere la chiave primaria.
Conclusione: La tabella NON è in 1NF a causa degli attributi composti.
Per portare la tabella in 1NF, scomponiamo gli attributi composti in attributi atomici:
- "Responsabile" → "NomeResp" + "CognomeResp"
- "NomeDipendente" → "NomeDipendente" + "CognomeDipendente"
Tabella in 1NF:
| CodiceProgetto | NomeProgetto | Budget | NomeResp | CognomeResp | EmailResponsabile |
CodiceDipendente | NomeDipendente | CognomeDipendente | Ruolo | OreAssegnate | TariffaOraria |
| PJ001 | Sistema CRM | 50000 | Marco | Bianchi | marco.bianchi@azienda.it |
D101 | Laura | Rossi | Sviluppatore | 120 | 40 |
| PJ001 | Sistema CRM | 50000 | Marco | Bianchi | marco.bianchi@azienda.it |
D102 | Giuseppe | Verdi | Analista | 80 | 50 |
| PJ002 | App Mobile | 30000 | Anna | Neri | anna.neri@azienda.it |
D101 | Laura | Rossi | Sviluppatore | 200 | 40 |
Chiave primaria: (CodiceProgetto, CodiceDipendente)
Verifica 1NF per la tabella modificata:
- Attributi atomici: ✅ Tutti gli attributi sono atomici. Gli attributi composti sono stati scomposti:
- "Responsabile" → "NomeResp" + "CognomeResp"
- "NomeDipendente" → "NomeDipendente" + "CognomeDipendente"
- Assenza di attributi multivalore: ✅ Ogni cella contiene un solo valore.
- Chiave primaria definita: ✅ (CodiceProgetto, CodiceDipendente) è la chiave primaria e identifica univocamente ogni riga.
Conclusione: La tabella è ora in 1NF.
Passo 2 (2NF?)
Devo verificare la 2NF per la tabella ottenuta al passo precedente (la tabella in 1NF). Verifico: (1) è già in 1NF (sì, dal passo 1); (2) ogni attributo non-chiave dipende dall'intera chiave primaria e non solo da una sua parte.
Verifica 2NF per la tabella:
- Già in 1NF: ✅ Verificato nel passo precedente.
- Assenza di dipendenze parziali: ❌ La chiave è (CodiceProgetto, CodiceDipendente). Ci sono attributi che dipendono solo da una parte della chiave:
- NomeProgetto, Budget, NomeResp, CognomeResp, EmailResponsabile dipendono solo da CodiceProgetto
- NomeDipendente, CognomeDipendente, Ruolo, TariffaOraria dipendono solo da CodiceDipendente
La tabella NON è in 2NF.
La tabella non è in 2NF. Applico il seguente procedimento ad ogni parte della chiave primaria che genera dipendenze parziali: creo una nuova tabella formata da quella parte della chiave (che diventa chiave primaria della nuova tabella) più tutti gli attributi che ne dipendono. La tabella originale viene ridotta ai soli attributi che dipendono dall'intera chiave originaria, che resta invariata come sua chiave primaria. Nel nostro caso:
- NomeProgetto, Budget, NomeResp, CognomeResp, EmailResponsabile dipendono solo da CodiceProgetto → creo la tabella Progetti (CodiceProgetto, NomeProgetto, Budget, NomeResp, CognomeResp, EmailResponsabile) con chiave primaria CodiceProgetto.
- NomeDipendente, CognomeDipendente, Ruolo, TariffaOraria dipendono solo da CodiceDipendente → creo la tabella Dipendenti (CodiceDipendente, NomeDipendente, CognomeDipendente, Ruolo, TariffaOraria) con chiave primaria CodiceDipendente.
- Nella tabella originaria resta solo OreAssegnate (che dipende dall'intera chiave) → diventa la tabella Assegnazioni (CodiceProgetto, CodiceDipendente, OreAssegnate) con chiave primaria (CodiceProgetto, CodiceDipendente).
Trasformazione in 2NF: Scomporre la tabella eliminando le dipendenze parziali.
Tabella Progetti (✅ 2NF):
Chiave primaria: CodiceProgetto
Tabella Dipendenti (✅ 2NF):
| CodiceDipendente | NomeDipendente | CognomeDipendente | Ruolo | TariffaOraria |
| D101 | Laura | Rossi | Sviluppatore | 40 |
| D102 | Giuseppe | Verdi | Analista | 50 |
Chiave primaria: CodiceDipendente
Tabella Assegnazioni (✅ 2NF):
| CodiceProgetto | CodiceDipendente | OreAssegnate |
| PJ001 | D101 | 120 |
| PJ001 | D102 | 80 |
| PJ002 | D101 | 200 |
Chiave primaria: (CodiceProgetto, CodiceDipendente)
Verifica 2NF per la tabella Progetti:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (CodiceProgetto).
- Assenza di dipendenze parziali: ✅ La chiave primaria è composta da un solo attributo (CodiceProgetto), quindi la tabella è automaticamente in 2NF.
Verifica 2NF per la tabella Dipendenti:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (CodiceDipendente).
- Assenza di dipendenze parziali: ✅ La chiave primaria è composta da un solo attributo (CodiceDipendente), quindi la tabella è automaticamente in 2NF.
Verifica 2NF per la tabella Assegnazioni:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (CodiceProgetto, CodiceDipendente).
- Assenza di dipendenze parziali: ✅ L'unico attributo non-chiave è OreAssegnate. OreAssegnate dipende dall'intera chiave (CodiceProgetto, CodiceDipendente): le ore assegnate a un dipendente specifico in un progetto specifico. Non ci sono attributi che dipendono solo da una parte della chiave.
Conclusione: Le tre tabelle Progetti, Dipendenti e Assegnazioni sono ora in 2NF.
Passo 3 (3NF?)
Devo verificare la 3NF per ogni tabella ottenuta al passo precedente (Progetti, Dipendenti, Assegnazioni). Per ciascuna verifico: (1) è già in 2NF (sì, dal passo 2); (2) non ci sono attributi non-chiave che dipendono da altri attributi non-chiave (dipendenze transitive).
Verifica 3NF per Progetti:
- Già in 2NF: ✅ Verificato nel passo precedente.
Verifica 3NF per Dipendenti:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ❌ C'è una dipendenza transitiva: TariffaOraria dipende da Ruolo (attributo non-chiave). La tabella NON è in 3NF.
Verifica 3NF per Assegnazioni:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ L'unico attributo non-chiave è OreAssegnate, che dipende direttamente dalla chiave primaria (CodiceProgetto, CodiceDipendente). La tabella è in 3NF.
Le tabelle Progetti e Dipendenti non sono in 3NF. Applico il seguente procedimento: per ogni dipendenza transitiva individuata, creo una nuova tabella formata dall'attributo non-chiave da cui dipendono gli altri attributi (che diventa chiave primaria della nuova tabella) più gli attributi che ne dipendono e, create le tabelle come descritto, considero la tabella originale riformulata eliminando gli attributi che dipendono da attributi non chiave. Nel nostro caso:
-
Responsabili (EmailResponsabile, NomeResp, CognomeResp) con chiave primaria EmailResponsabile.
- Dalla tabella Progetti rimuovo NomeResp, CognomeResp ; EmailResponsabile viene aggiunto come chiave esterna → diventa ProgettiRiformulata (CodiceProgetto, NomeProgetto, Budget, EmailResponsabile).
- TariffaOraria dipende da Ruolo → creo la tabella Ruoli (Ruolo, TariffaOraria) con chiave primaria Ruolo.
- Dalla tabella Dipendenti rimuovo TariffaOraria; Ruolo resta come chiave esterna verso Ruoli → diventa DipendentiRiformulata (CodiceDipendente, NomeDipendente, CognomeDipendente, Ruolo).
Trasformazione in 3NF: Scomporre le tabelle con dipendenze transitive.
Tabella Responsabili (✅ 3NF):
| EmailResponsabile | NomeResp | CognomeResp |
| marco.bianchi@azienda.it | Marco | Bianchi |
| anna.neri@azienda.it | Anna | Neri |
Chiave primaria: EmailResponsabile
Tabella ProgettiRiformulata (✅ 3NF):
| CodiceProgetto | NomeProgetto | Budget | EmailResponsabile |
| PJ001 | Sistema CRM | 50000 | marco.bianchi@azienda.it |
| PJ002 | App Mobile | 30000 | anna.neri@azienda.it< |
Chiave primaria: CodiceProgetto
Tabella DipendentiRiformulata (✅ 3NF):
| CodiceDipendente | NomeDipendente | CognomeDipendente | Ruolo |
| D101 | Laura | Rossi | Sviluppatore |
| D102 | Giuseppe | Verdi | Analista |
Chiave primaria: CodiceDipendente
Tabella Ruoli (✅ 3NF):
| Ruolo | TariffaOraria |
| Sviluppatore | 40 |
| Analista | 50 |
Chiave primaria: Ruolo
Verifica 3NF per la tabella Responsabili:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (EmailResponsabile), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (NomeResp, CognomeResp) dipendono direttamente dalla chiave primaria EmailResponsabile. Non ci sono attributi che dipendono da altri attributi non-chiave.
Verifica 3NF per la tabella ProgettiRiformulata:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (CodiceProgetto), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (NomeProgetto, Budget, EmailResponsabile) dipendono direttamente dalla chiave primaria CodiceProgetto. EmailResponsabile è chiave esterna che fa riferimento alla tabella Responsabili.
Verifica 3NF per la tabella DipendentiRiformulata:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (CodiceDipendente), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (NomeDipendente, CognomeDipendente, Ruolo) dipendono direttamente dalla chiave primaria CodiceDipendente. Ruolo è chiave esterna che fa riferimento alla tabella Ruoli.
Verifica 3NF per la tabella Ruoli:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (Ruolo), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ L'unico attributo non-chiave è TariffaOraria, che dipende direttamente dalla chiave primaria Ruolo. Non ci sono attributi che dipendono da altri attributi non-chiave.
Verifica 3NF per la tabella Assegnazioni:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ L'unico attributo non-chiave è OreAssegnate, che dipende direttamente dalla chiave primaria (CodiceProgetto, CodiceDipendente). La tabella è in 3NF.
Conclusione: Le tabelle finali in 3NF sono:
- Responsabili (EmailResponsabile, NomeResp, CognomeResp)
- ProgettiRiformulata (CodiceProgetto, NomeProgetto, Budget, EmailResponsabile)
- DipendentiRiformulata (CodiceDipendente, NomeDipendente, CognomeDipendente, Ruolo)
- Ruoli (Ruolo, TariffaOraria)
- Assegnazioni (CodiceProgetto, CodiceDipendente, OreAssegnate)
Esercizio 8 – Gestione Farmacia
Una farmacia gestisce le vendite di medicinali. La seguente tabella contiene tutte le informazioni:
| NumeroScontrino | DataVendita | CodiceFarmacista | NomeFarmacista | OrarioTurno |
CodiceProdotto | NomeProdotto | Categoria | PrincipioAttivo | Quantità | PrezzoUnitario |
| S001 | 2024-03-10 | F101 | Maria Bianchi | Mattina |
MED001 | Tachipirina | Antipiretico | Paracetamolo | 2 | 5.50 |
| S001 | 2024-03-10 | F101 | Maria Bianchi | Mattina |
MED002 | Moment | Antinfiammatorio | Ibuprofene | 1 | 8.00 |
| S002 | 2024-03-10 | F102 | Luigi Verdi | Pomeriggio |
MED001 | Tachipirina | Antipiretico | Paracetamolo | 3 | 5.50 |
La tabella è in 3FN? Soluzione:
Passo 1 (1NF?)
Verifica 1NF per la tabella iniziale:
- Attributi atomici: ❌ Attributo composto presente:
- "NomeFarmacista" contiene nome e cognome insieme
- Assenza di attributi multivalore: ✅
- Chiave primaria definita: ✅ (NumeroScontrino, CodiceProdotto) può essere la chiave primaria.
Conclusione: La tabella NON è in 1NF a causa dell'attributo composto.
Trasformazione in 1NF: Scomporre l'attributo composto "NomeFarmacista".
Tabella in 1NF:
| NumeroScontrino | DataVendita | CodiceFarmacista | NomeFarm | CognomeFarm | OrarioTurno |
CodiceProdotto | NomeProdotto | Categoria | PrincipioAttivo | Quantità | PrezzoUnitario |
| S001 | 2024-03-10 | F101 | Maria | Bianchi | Mattina |
MED001 | Tachipirina | Antipiretico | Paracetamolo | 2 | 5.50 |
| S001 | 2024-03-10 | F101 | Maria | Bianchi | Mattina |
MED002 | Moment | Antinfiammatorio | Ibuprofene | 1 | 8.00 |
| S002 | 2024-03-10 | F102 | Luigi | Verdi | Pomeriggio |
MED001 | Tachipirina | Antipiretico | Paracetamolo | 3 | 5.50 |
Chiave primaria: (NumeroScontrino, CodiceProdotto)
Verifica 1NF per la tabella modificata:
- Attributi atomici: ✅ Tutti gli attributi sono atomici. L'attributo composto è stato scomposto:
- "NomeFarmacista" → "NomeFarm" + "CognomeFarm"
- Assenza di attributi multivalore: ✅ Ogni cella contiene un solo valore.
- Chiave primaria definita: ✅ (NumeroScontrino, CodiceProdotto) è la chiave primaria e identifica univocamente ogni riga.
Conclusione: La tabella è ora in 1NF.
Passo 2 (2NF?)
Devo verificare la 2NF per la tabella ottenuta al passo precedente (la tabella in 1NF). Verifico: (1) è già in 1NF (sì, dal passo 1); (2) ogni attributo non-chiave dipende dall'intera chiave primaria e non solo da una sua parte.
Verifica 2NF per la tabella:
- Già in 1NF: ✅ Verificato nel passo precedente.
- Assenza di dipendenze parziali: ❌ La chiave è (NumeroScontrino, CodiceProdotto). Ci sono attributi che dipendono solo da una parte della chiave:
- DataVendita, CodiceFarmacista, NomeFarm, CognomeFarm, OrarioTurno dipendono solo da NumeroScontrino
- NomeProdotto, Categoria, PrincipioAttivo, PrezzoUnitario dipendono solo da CodiceProdotto
La tabella NON è in 2NF.
La tabella non è in 2NF. Applico il seguente procedimento ad ogni parte della chiave primaria che genera dipendenze parziali: creo una nuova tabella formata da quella parte della chiave (che diventa chiave primaria della nuova tabella) più tutti gli attributi che ne dipendono. La tabella originale viene ridotta ai soli attributi che dipendono dall'intera chiave originaria, che resta invariata come sua chiave primaria. Nel nostro caso:
- DataVendita, CodiceFarmacista, NomeFarm, CognomeFarm, OrarioTurno dipendono solo da NumeroScontrino → creo la tabella Scontrini (NumeroScontrino, DataVendita, CodiceFarmacista, NomeFarm, CognomeFarm, OrarioTurno) con chiave primaria NumeroScontrino.
- NomeProdotto, Categoria, PrincipioAttivo, PrezzoUnitario dipendono solo da CodiceProdotto → creo la tabella Prodotti (CodiceProdotto, NomeProdotto, Categoria, PrincipioAttivo, PrezzoUnitario) con chiave primaria CodiceProdotto.
- Nella tabella originaria resta solo Quantità (che dipende dall'intera chiave) → diventa la tabella DettagliVendita (NumeroScontrino, CodiceProdotto, Quantità) con chiave primaria (NumeroScontrino, CodiceProdotto).
Trasformazione in 2NF: Scomporre la tabella eliminando le dipendenze parziali.
Tabella Scontrini (✅ 2NF):
| NumeroScontrino | DataVendita | CodiceFarmacista | NomeFarm | CognomeFarm | OrarioTurno |
| S001 | 2024-03-10 | F101 | Maria | Bianchi | Mattina |
| S002 | 2024-03-10 | F102 | Luigi | Verdi | Pomeriggio |
Chiave primaria: NumeroScontrino
Tabella Prodotti (✅ 2NF):
| CodiceProdotto | NomeProdotto | Categoria | PrincipioAttivo | PrezzoUnitario |
| MED001 | Tachipirina | Antipiretico | Paracetamolo | 5.50 |
| MED002 | Moment | Antinfiammatorio | Ibuprofene | 8.00 |
Chiave primaria: CodiceProdotto
Tabella DettagliVendita (✅ 2NF):
| NumeroScontrino | CodiceProdotto | Quantità |
| S001 | MED001 | 2 |
| S001 | MED002 | 1 |
| S002 | MED001 | 3 |
Chiave primaria: (NumeroScontrino, CodiceProdotto)
Verifica 2NF per la tabella Scontrini:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (NumeroScontrino).
- Assenza di dipendenze parziali: ✅ La chiave primaria è composta da un solo attributo (NumeroScontrino), quindi la tabella è automaticamente in 2NF.
Verifica 2NF per la tabella Prodotti:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (CodiceProdotto).
- Assenza di dipendenze parziali: ✅ La chiave primaria è composta da un solo attributo (CodiceProdotto), quindi la tabella è automaticamente in 2NF.
Verifica 2NF per la tabella DettagliVendita:
- Già in 1NF: ✅ Tutti gli attributi sono atomici, non ci sono attributi multivalore, chiave primaria definita (NumeroScontrino, CodiceProdotto).
- Assenza di dipendenze parziali: ✅ L'unico attributo non-chiave è Quantità. Quantità dipende dall'intera chiave (NumeroScontrino, CodiceProdotto): la quantità di un prodotto specifico in uno scontrino specifico. Non ci sono attributi che dipendono solo da una parte della chiave.
Conclusione: Le tre tabelle Scontrini, Prodotti e DettagliVendita sono ora in 2NF.
Passo 3 (3NF?)
Devo verificare la 3NF per ogni tabella ottenuta al passo precedente (Scontrini, Prodotti, DettagliVendita). Per ciascuna verifico: (1) è già in 2NF (sì, dal passo 2); (2) non ci sono attributi non-chiave che dipendono da altri attributi non-chiave (dipendenze transitive).
Verifica 3NF per Scontrini:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ❌ C'è una dipendenza transitiva: NomeFarm e CognomeFarm dipendono da CodiceFarmacista (attributo non-chiave). Inoltre OrarioTurno dipende da CodiceFarmacista (ogni farmacista ha un turno specifico). La tabella NON è in 3NF.
Verifica 3NF per Prodotti:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (NomeProdotto, Categoria, PrincipioAttivo, PrezzoUnitario) dipendono direttamente dalla chiave primaria CodiceProdotto. Non ci sono attributi che dipendono da altri attributi non-chiave. La tabella è in 3NF.
Verifica 3NF per DettagliVendita:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ L'unico attributo non-chiave è Quantità, che dipende direttamente dalla chiave primaria (NumeroScontrino, CodiceProdotto). La tabella è in 3NF.
Solo la tabella Scontrini non è in 3NF. Applico il seguente procedimento: per ogni dipendenza transitiva individuata, creo una nuova tabella formata dall'attributo non-chiave da cui dipendono gli altri attributi (che diventa chiave primaria della nuova tabella) più gli attributi che ne dipendono e, create le tabelle come descritto, considero la tabella originale riformulata eliminando gli attributi che dipendono da attributi non chiave. Nel nostro caso:
- NomeFarm, CognomeFarm e OrarioTurno dipendono da CodiceFarmacista → creo la tabella Farmacisti (CodiceFarmacista, NomeFarm, CognomeFarm, OrarioTurno) con chiave primaria CodiceFarmacista.
- Dalla tabella Scontrini rimuovo NomeFarm, CognomeFarm e OrarioTurno; CodiceFarmacista resta come chiave esterna verso Farmacisti → diventa ScontriniRiformulata (NumeroScontrino, DataVendita, CodiceFarmacista).
Trasformazione in 3NF: Scomporre la tabella Scontrini eliminando le dipendenze transitive.
Tabella Farmacisti (✅ 3NF):
| CodiceFarmacista | NomeFarm | CognomeFarm | OrarioTurno |
| F101 | Maria | Bianchi | Mattina |
| F102 | Luigi | Verdi | Pomeriggio |
Chiave primaria: CodiceFarmacista
Tabella ScontriniRiformulata (✅ 3NF):
| NumeroScontrino | DataVendita | CodiceFarmacista |
| S001 | 2024-03-10 | F101 |
| S002 | 2024-03-10 | F102 |
Chiave primaria: NumeroScontrino
Verifica 3NF per la tabella Farmacisti:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (CodiceFarmacista), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (NomeFarm, CognomeFarm, OrarioTurno) dipendono direttamente dalla chiave primaria CodiceFarmacista. Non ci sono attributi che dipendono da altri attributi non-chiave.
Verifica 3NF per la tabella ScontriniRiformulata:
- Già in 2NF: ✅ La chiave primaria è composta da un solo attributo (NumeroScontrino), quindi è automaticamente in 2NF.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (DataVendita, CodiceFarmacista) dipendono direttamente dalla chiave primaria NumeroScontrino. CodiceFarmacista è chiave esterna che fa riferimento alla tabella Farmacisti.
Verifica 3NF per la tabella Prodotti:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ Tutti gli attributi non-chiave (NomeProdotto, Categoria, PrincipioAttivo, PrezzoUnitario) dipendono direttamente dalla chiave primaria CodiceProdotto. La tabella è in 3NF.
Verifica 3NF per la tabella DettagliVendita:
- Già in 2NF: ✅ Verificato nel passo precedente.
- Assenza di attributi dipendenti da attributi non chiave: ✅ L'unico attributo non-chiave è Quantità, che dipende direttamente dalla chiave primaria (NumeroScontrino, CodiceProdotto). La tabella è in 3NF.
Conclusione: Le tabelle finali in 3NF sono:
- Farmacisti (CodiceFarmacista, NomeFarm, CognomeFarm, OrarioTurno)
- ScontriniRiformulata (NumeroScontrino, DataVendita, CodiceFarmacista)
- Prodotti (CodiceProdotto, NomeProdotto, Categoria, PrincipioAttivo, PrezzoUnitario)
- DettagliVendita (NumeroScontrino, CodiceProdotto, Quantità)
Riepilogo degli Esercizi Aggiuntivi
| Esercizio |
Contesto |
Problemi 1NF |
Problemi 2NF |
Problemi 3NF |
Tabelle Finali |
| 6. Hotel |
Prenotazioni hotel |
Attributi multivalore (servizi) |
Nessuno (chiavi singole) |
Dipendenza di telefono da nome cliente e prezzo da tipo camera |
4 tabelle |
| 7. Progetti |
Gestione progetti aziendali |
Attributi composti (responsabile e nome dipendente) |
Dipendenze parziali da CodiceProgetto e CodiceDipendente |
Dipendenza di EmailResponsabile da (NomeResp, CognomeResp) e di TariffaOraria da Ruolo |
5 tabelle |
| 8. Farmacia |
Vendite farmaceutiche |
Attributo composto (nome farmacista) |
Dipendenze parziali da NumeroScontrino e CodiceProdotto |
Dipendenza di NomeFarm, CognomeFarm e OrarioTurno da CodiceFarmacista |
4 tabelle |