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
giulia.bianchi@email.com
ORD002
2024-01-16
Mario Rossi
Via Roma 10, Milano
02-1234567
Monitor
1
150
Giulia Bianchi
giulia.bianchi@email.com
ORD003
2024-01-17
Anna Verdi
Via Dante 5, Roma
06-7654321
Laptop Cuffie
2 2
1200 50
Marco Neri
marco.neri@email.com
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 "luca.verdi@email.com".
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:
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 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
giulia.bianchi@email.com
ORD002
2024-01-16
Mario
Rossi
Via Roma
10
Milano
02-1234567
Giulia
Bianchi
giulia.bianchi@email.com
ORD003
2024-01-17
Anna
Verdi
Via Dante
5
Roma
06-7654321
Marco
Neri
marco.neri@email.com
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:
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
18
Tastiera
35
Monitor
150
Cuffie
50
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):
CodiceVenditore
NomeVenditore
CognomeVenditore
EmailVenditore
V001
Giulia
Bianchi
giulia.bianchi@email.com
V002
Marco
Neri
marco.neri@email.com
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:
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
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", "CognomeAutore") (attributi non-chiave)
Esercizio 2 (Palestra): "NomeIstruttore" e "CognomeIstruttore" dipendono da "TelefonoIstruttore" (attributo non-chiave)
Esercizio 5 (Negozio): "IndirizzoFornitore" dipende da "Fornitore" (attributo non-chiave)
Attributo multivalore: "Genere" viene estratto in una tabella separata formata dal codice del libro (CodiceLibro) e dal valore dell'attributo multivalore (Genere).
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).
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.
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).
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.
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).
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.
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.
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:
NomeCliente e CognomeCliente dipendono da TelefonoCliente → 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.
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.
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.
Assenza di attributi dipendenti da attributi non chiave: ❌ C'è una dipendenza transitiva: NomeResp e CognomeResp dipendono da EmailResponsabile (attributo non-chiave). La tabella NON è in 3NF.
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:
NomeResp e CognomeResp dipendono da EmailResponsabile → creo la tabella 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.
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.
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.