📘 Tutorial completo: Normalizzazione nei database

La normalizzazione elimina ridondanze e anomalie di inserimento, cancellazione e aggiornamento. Vediamo le tre forme normali (1NF, 2NF, 3NF) con esempi reali e diagrammi illustrativi.

🔹 1. Prima Forma Normale (1NF)

📌 Regole della 1NF:

❌ Esempio che VIOLA la 1NF

Tabella "Studenti" con numeri di telefono multipli nella stessa cella e attributi ripetuti.

ID StudenteNomeTelefoniTelefono2
1Marco Rossi331123456, 331654321NULL
2Laura Bianchi392111222392333444

⚠️ Problemi: I telefoni non sono atomici (nel primo caso ci sono due numeri separati da virgola). Colonne Telefono1/Telefono2 creano ridondanza e difficoltà di ricerca.

✅ Esempio CORRETTO in 1NF

Suddivido i telefoni su righe distinte e creo una chiave primaria composta (ID_Studente, Telefono).

ID StudenteNomeTelefono
1Marco Rossi331123456
1Marco Rossi331654321
2Laura Bianchi392111222
2Laura Bianchi392333444
✅ Risultato: Ora ogni attributo è atomico e non esistono gruppi ripetuti. Ogni riga è univoca grazie alla coppia (ID_Studente, Telefono).
Diagramma 1NF - da valori multipli ad atomici
Figura 1: Trasformazione dalla violazione della 1NF alla corretta 1NF

🔸 2. Seconda Forma Normale (2NF)

📌 Regole della 2NF: Nota: la 2NF ha senso solo con chiavi primarie composte.

❌ Esempio che VIOLA la 2NF

Tabella "IscrizioniCorsi" con chiave primaria composta (ID_Studente, ID_Corso).

ID_StudenteID_CorsoNome_StudenteNome_CorsoData_Iscrizione
1101MarcoMatematica2025-01-10
1102MarcoFisica2025-01-12
2101LauraMatematica2025-01-11

⚠️ Problema: "Nome_Studente" dipende solo da ID_Studente (non da ID_Corso), e "Nome_Corso" dipende solo da ID_Corso. Sono dipendenze parziali → violazione 2NF. Ridondanza: "Marco" e "Matematica" vengono ripetuti più volte.

✅ Soluzione: scomposizione in 2NF

Creo tre tabelle separate, eliminando ogni dipendenza parziale:

📋 Tabella STUDENTI

ID_Studente (PK)Nome_Studente
1Marco
2Laura

📋 Tabella CORSI

ID_Corso (PK)Nome_Corso
101Matematica
102Fisica

📋 Tabella ISCRIZIONI (tabella ponte)

ID_Studente (FK)ID_Corso (FK)Data_Iscrizione
11012025-01-10
11022025-01-12
21012025-01-11
✅ Risultato: Ora ogni attributo non chiave dipende dall'intera chiave primaria della propria tabella. Nessuna ridondanza.
Diagramma 2NF - eliminazione dipendenze parziali
Figura 2: Scomposizione per eliminare le dipendenze parziali dalla chiave composta

🔹 3. Terza Forma Normale (3NF)

📌 Regole della 3NF:

❌ Esempio che VIOLA la 3NF

Tabella "Impiegati" in 2NF ma con dipendenza transitiva.

ID_ImpiegatoNomeID_UfficioCittà_Ufficio
10AnnaU1Roma
11LuigiU2Milano
12SofiaU1Roma

⚠️ Problema: "Città_Ufficio" dipende da "ID_Ufficio" (attributo non chiave), non direttamente da ID_Impiegato. Esiste una dipendenza transitiva:
ID_Impiegato → ID_Ufficio → Città_Ufficio.
Ridondanza: "Roma" ripetuta per ogni impiegato dello stesso ufficio.

Anomalie: se un ufficio cambia città, bisogna aggiornare tutte le righe degli impiegati (rischio inconsistenza).

✅ Soluzione: scomposizione in 3NF

Separare la dipendenza transitiva in una tabella dedicata agli uffici.

📋 Tabella IMPIEGATI (3NF)

ID_Impiegato (PK)NomeID_Ufficio (FK)
10AnnaU1
11LuigiU2
12SofiaU1

📋 Tabella UFFICI

ID_Ufficio (PK)Città_Ufficio
U1Roma
U2Milano
✅ Risultato: Ora non esistono dipendenze transitive: la città dell'ufficio si trova solo nella tabella Uffici. Se un ufficio cambia città, si modifica un solo record.
Diagramma 3NF - eliminazione dipendenze transitive
Figura 3: Eliminazione della dipendenza transitiva separando la tabella Uffici
Diagramma riepilogativo delle 3 forme normali
Figura 4: Riepilogo visivo dei tre passaggi di normalizzazione

📊 Riepilogo comparativo

Forma normaleRegola chiaveProblema risoltoQuando applicare
1NFAttributi atomici + chiave univocaDati multivalore, gruppi ripetutiSempre
2NFNessuna dipendenza parzialeRidondanza in chiave compostaCon chiavi primarie composte
3NFNessuna dipendenza transitivaRidondanza tra attributi non chiaveQuasi sempre (fino a 3NF è standard)

🎯 Conclusione:


📝 ESERCIZI: Normalizza tu stesso!

Di seguito trovi 4 esercizi di difficoltà crescente. Prova a normalizzare i dati fino alla 3NF, poi confronta con la soluzione.


✏️ Esercizio 1 - Raggiungi la 1NF

Consegna: La tabella "Libri" memorizza informazioni sui libri e i loro autori. Normalizza in 1NF.

Tabella di partenza (viola 1NF):

ID_LibroTitoloAutoriAnno
1Database FacileRossi, Bianchi2020
2SQL AvanzatoVerdi2021
3NoSQL GuidaNeri, Rossi, Gialli2022
🔍 Mostra soluzione Esercizio 1 (1NF)

Soluzione: Scomporre gli autori su righe separate. Chiave primaria composta (ID_Libro, Autore).

ID_LibroTitoloAutoreAnno
1Database FacileRossi2020
1Database FacileBianchi2020
2SQL AvanzatoVerdi2021
3NoSQL GuidaNeri2022
3NoSQL GuidaRossi2022
3NoSQL GuidaGialli2022

✅ Ora ogni cella contiene un valore atomico.


✏️ Esercizio 2 - Raggiungi la 2NF

Consegna: La tabella "OrdiniClienti" ha chiave primaria composta (ID_Ordine, ID_Prodotto). Normalizza in 2NF.

Tabella di partenza (in 1NF ma viola 2NF):

ID_OrdineID_ProdottoData_OrdineNome_ClienteProdotto_NomeQuantità
101P12025-01-10MarcoMouse2
101P22025-01-10MarcoTastiera1
102P12025-01-11LauraMouse3
🔍 Mostra soluzione Esercizio 2 (2NF)

Soluzione: Identificare le dipendenze parziali: Data_Ordine e Nome_Cliente dipendono solo da ID_Ordine. Prodotto_Nome dipende solo da ID_Prodotto. Creare 3 tabelle.

Tabella ORDINI:

ID_Ordine (PK)Data_OrdineNome_Cliente
1012025-01-10Marco
1022025-01-11Laura

Tabella PRODOTTI:

ID_Prodotto (PK)Prodotto_Nome
P1Mouse
P2Tastiera

Tabella DETTAGLI_ORDINE (tabella ponte):

ID_Ordine (FK)ID_Prodotto (FK)Quantità
101P12
101P21
102P13

✅ Eliminate tutte le dipendenze parziali.


✏️ Esercizio 3 - Raggiungi la 3NF

Consegna: La tabella "ProgettiDipendenti" è già in 2NF, ma ha una dipendenza transitiva. Normalizza in 3NF.

Tabella di partenza (in 2NF, viola 3NF):

ID_DipendenteNome_DipendenteID_ProgettoNome_ProgettoRepartoEdificio_Reparto
D1AnnaPRJ1AIR&DEdificio A
D2LuigiPRJ1AIR&DEdificio A
D3SofiaPRJ2CloudInfrastruttureEdificio B

Suggerimento: Individua la dipendenza transitiva: ID_Dipendente → ? → ?

🔍 Mostra soluzione Esercizio 3 (3NF)

Soluzione: Dipendenza transitiva: ID_Dipendente → Reparto → Edificio_Reparto. Inoltre Nome_Progetto dipende da ID_Progetto (altro attributo non chiave).

Tabella DIPENDENTI_PROGETTI (relazione pura):

ID_DipendenteID_Progetto
D1PRJ1
D2PRJ1
D3PRJ2

Tabella DIPENDENTI:

ID_Dipendente (PK)Nome_DipendenteReparto
D1AnnaR&D
D2LuigiR&D
D3SofiaInfrastrutture

Tabella REPARTI:

Reparto (PK)Edificio_Reparto
R&DEdificio A
InfrastruttureEdificio B

Tabella PROGETTI:

ID_Progetto (PK)Nome_Progetto
PRJ1AI
PRJ2Cloud

✅ Eliminate tutte le dipendenze transitive.


✏️ Esercizio 4 - Sfida completa (1NF → 2NF → 3NF)

Consegna: La tabella "CorsiStudentiDocenti" riassume corsi, studenti e docenti. Normalizza completamente fino alla 3NF.

Tabella di partenza (non normalizzata):

ID_CorsoNome_CorsoStudenti (lista)ID_DocenteNome_DocenteSpecializzazione_Docente
CS101DatabaseMarco, LauraD10RossiSQL, NoSQL
CS102PythonMarco, Sofia, LuigiD20BianchiPython, Django
CS101DatabaseSofiaD10RossiSQL, NoSQL
🔍 Mostra soluzione Esercizio 4 (3NF completa)

Soluzione passo passo:

  1. 1NF: Scomporre studenti e specializzazioni in righe atomiche.
  2. 2NF: Identificare dipendenze parziali (Nome_Corso dipende solo da ID_Corso).
  3. 3NF: Eliminare dipendenze transitive (Specializzazione_Docente dipende da ID_Docente).

Tabella CORSI:

ID_Corso (PK)Nome_Corso
CS101Database
CS102Python

Tabella DOCENTI:

ID_Docente (PK)Nome_Docente
D10Rossi
D20Bianchi

Tabella SPECIALIZZAZIONI_DOCENTE (1NF per le specializzazioni):

ID_Docente (FK)Specializzazione
D10SQL
D10NoSQL
D20Python
D20Django

Tabella STUDENTI (dall'estrazione degli studenti unici):

ID_Studente (generato)Nome_Studente
S1Marco
S2Laura
S3Sofia
S4Luigi

Tabella ISCRIZIONI_CORSI (relazione studenti-corsi):

ID_Studente (FK)ID_Corso (FK)
S1CS101
S2CS101
S1CS102
S3CS102
S4CS102
S3CS101

Tabella ASSEGNAZIONE_DOCENTI (un corso può avere un docente):

ID_Corso (FK)ID_Docente (FK)
CS101D10
CS102D20

✅ Database completamente normalizzato in 3NF, senza ridondanze né anomalie.


📌 Autovalutazione

Dopo aver completato gli esercizi, verifica di aver compreso:

💡 Suggerimento finale: Per verificare se hai normalizzato correttamente, controlla che:
- Ogni tabella rappresenti un unico concetto (entità).
- Tutti gli attributi non chiave descrivano completamente la chiave primaria (e solo quella).
- Non ci siano catene di dipendenze tra attributi non chiave.

📚 Esercizi tratti da casi reali - Prova a inventare nuovi esempi dalla tua esperienza per allenarti ulteriormente!