Codice dei programmi nella directory:

///File: TutorialFormeNormali2026-CON-SOLUZIONE-ESERCIZI.html
<!DOCTYPE html> <html lang="it"> <head> <meta charset="UTF-8"> <title>Tutorial Normalizzazione Database - 1NF, 2NF, 3NF - F. Sacco - Maggio 2026</title> <style> body { font-family: Arial, sans-serif; margin: 2cm; line-height: 1.4; max-width: 1200px; margin-left: auto; margin-right: auto; } h1 { color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 5px; } h2 { color: #2980b9; margin-top: 35px; border-left: 5px solid #3498db; padding-left: 15px; } h3 { color: #16a085; margin-top: 25px; } table { border-collapse: collapse; width: 100%; margin: 20px 0; background: #f9f9f9; box-shadow: 0 1px 3px rgba(0,0,0,0.1); } th, td { border: 1px solid #aaa; padding: 10px; text-align: left; vertical-align: top; } th { background: #ecf0f1; font-weight: bold; } .wrong { border-left: 5px solid #e74c3c; padding-left: 15px; background: #fceaea; margin: 15px 0; } .correct { border-left: 5px solid #2ecc71; padding-left: 15px; background: #e8f8f5; margin: 15px 0; } .image-container { text-align: center; margin: 25px 0; background: #fef9e7; padding: 15px; border-radius: 8px; border: 1px solid #f39c12; } .image-container img { max-width: 100%; height: auto; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .image-container .caption { font-style: italic; margin-top: 10px; color: #7f8c8d; font-size: 0.9em; } .rule-box { background: #e8f8f5; padding: 15px; border-radius: 8px; margin: 20px 0; border-left: 5px solid #1abc9c; } .summary-table { background: #ecf0f1; } .salto-pagina { page-break-before: always; } hr { margin: 40px 0; border: 1px solid #bdc3c7; } </style> </head> <body> <h1>📘 Tutorial completo: Normalizzazione nei database</h1> <p>La normalizzazione elimina ridondanze e anomalie di inserimento, cancellazione e aggiornamento. Vediamo le <strong>tre forme normali (1NF, 2NF, 3NF)</strong> con esempi reali e diagrammi illustrativi.</p> <!-- ============================================= --> <!-- PRIMA FORMA NORMALE --> <!-- ============================================= --> <h2>🔹 1. Prima Forma Normale (1NF)</h2> <div class="rule-box"> <strong>📌 Regole della 1NF:</strong> <ul> <li>Ogni colonna deve contenere valori <strong>atomici</strong> (indivisibili).</li> <li>Non sono ammesse ripetizioni di gruppi di colonne (es. Telefono1, Telefono2).</li> <li>Ogni riga deve essere univocamente identificabile (chiave primaria).</li> </ul> </div> <h3>❌ Esempio che VIOLA la 1NF</h3> <p>Tabella "Studenti" con numeri di telefono multipli nella stessa cella e attributi ripetuti.</p> <table> <tr><th>ID Studente</th><th>Nome</th><th>Telefoni</th><th>Telefono2</th></tr> <tr><td style="text-align: center">1</td><td>Marco Rossi</td><td>331123456, 331654321</td><td>NULL</td></tr> <tr><td style="text-align: center">2</td><td>Laura Bianchi</td><td>392111222</td><td>392333444</td></tr> </table> <p><strong>⚠️ Problemi:</strong> I telefoni non sono atomici (nel primo caso ci sono due numeri separati da virgola). Colonne Telefono1/Telefono2 creano ridondanza e difficoltà di ricerca.</p> <h3>✅ Esempio CORRETTO in 1NF</h3> <p>Suddivido i telefoni su righe distinte e creo una chiave primaria composta (ID_Studente, Telefono).</p> <table> <tr><th>ID Studente</th><th>Nome</th><th>Telefono</th></tr> <tr><td style="text-align: center">1</td><td>Marco Rossi</td><td>331123456</td></tr> <tr><td style="text-align: center">1</td><td>Marco Rossi</td><td>331654321</td></tr> <tr><td style="text-align: center">2</td><td>Laura Bianchi</td><td>392111222</td></tr> <tr><td style="text-align: center">2</td><td>Laura Bianchi</td><td>392333444</td></tr> </table> <div class="correct"> <strong>✅ Risultato:</strong> Ora ogni attributo è atomico e non esistono gruppi ripetuti. Ogni riga è univoca grazie alla coppia (ID_Studente, Telefono). </div> <!-- Immagine 1: Diagramma 1NF --> <div class="image-container"> <img src="immagine1.jpg" alt="Diagramma 1NF - da valori multipli ad atomici" onerror="this.style.display='none'"> <div class="caption">Figura 1: Trasformazione dalla violazione della 1NF alla corretta 1NF</div> </div> <!-- ============================================= --> <!-- SECONDA FORMA NORMALE --> <!-- ============================================= --> <h2>🔸 2. Seconda Forma Normale (2NF)</h2> <div class="rule-box"> <strong>📌 Regole della 2NF:</strong> <ul> <li>La tabella deve essere già in 1NF.</li> <li><strong>Nessuna dipendenza parziale</strong> dalla chiave primaria: ogni colonna non chiave deve dipendere dall'<em>intera</em> chiave primaria (non solo da una parte).</li> </ul> <em>Nota: la 2NF ha senso solo con chiavi primarie composte.</em> </div> <h3>❌ Esempio che VIOLA la 2NF</h3> <p>Tabella "IscrizioniCorsi" con chiave primaria composta (ID_Studente, ID_Corso).</p> <table> <tr><th>ID_Studente</th><th>ID_Corso</th><th>Nome_Studente</th><th>Nome_Corso</th><th>Data_Iscrizione</th></tr> <tr><td style="text-align: center">1</td><td style="text-align: center">101</td><td>Marco</td><td>Matematica</td><td>2025-01-10</td></tr> <tr><td style="text-align: center">1</td><td style="text-align: center">102</td><td>Marco</td><td>Fisica</td><td>2025-01-12</td></tr> <tr><td style="text-align: center">2</td><td style="text-align: center">101</td><td>Laura</td><td>Matematica</td><td>2025-01-11</td></tr> </table> <p><strong>⚠️ Problema:</strong> "Nome_Studente" dipende solo da ID_Studente (non da ID_Corso), e "Nome_Corso" dipende solo da ID_Corso. Sono <strong>dipendenze parziali</strong> → violazione 2NF. Ridondanza: "Marco" e "Matematica" vengono ripetuti più volte.</p> <h3>✅ Soluzione: scomposizione in 2NF</h3> <p>Creo tre tabelle separate, eliminando ogni dipendenza parziale:</p> <p><strong>📋 Tabella STUDENTI</strong></p> <table> <tr><th>ID_Studente (PK)</th><th>Nome_Studente</th><tr> <tr><td style="text-align: center">1</td><td>Marco</td></tr> <tr><td style="text-align: center">2</td><td>Laura</td></tr> </table> <p><strong>📋 Tabella CORSI</strong></p> <table> <tr><th>ID_Corso (PK)</th><th>Nome_Corso</th></tr> <tr><td style="text-align: center">101</td><td>Matematica</td></tr> <tr><td style="text-align: center">102</td><td>Fisica</td></tr> </table> <p><strong>📋 Tabella ISCRIZIONI (tabella ponte)</strong></p> <table> <tr><th>ID_Studente (FK)</th><th>ID_Corso (FK)</th><th>Data_Iscrizione</th></tr> <tr><td style="text-align: center">1</td><td style="text-align: center">101</td><td>2025-01-10</td></tr> <tr><td style="text-align: center">1</td><td style="text-align: center">102</td><td>2025-01-12</td></tr> <tr><td style="text-align: center">2</td><td style="text-align: center">101</td><td>2025-01-11</td></tr> </table> <div class="correct"> <strong>✅ Risultato:</strong> Ora ogni attributo non chiave dipende dall'intera chiave primaria della propria tabella. Nessuna ridondanza. </div> <!-- Immagine 2: Diagramma 2NF --> <div class="image-container"> <img src="immagine2.jpg" alt="Diagramma 2NF - eliminazione dipendenze parziali" onerror="this.style.display='none'"> <div class="caption">Figura 2: Scomposizione per eliminare le dipendenze parziali dalla chiave composta</div> </div> <!-- ============================================= --> <!-- TERZA FORMA NORMALE --> <!-- ============================================= --> <h2>🔹 3. Terza Forma Normale (3NF)</h2> <div class="rule-box"> <strong>📌 Regole della 3NF:</strong> <ul> <li>La tabella deve essere già in 2NF.</li> <li><strong>Nessuna dipendenza transitiva</strong>: un attributo non chiave non può dipendere da un altro attributo non chiave.</li> </ul> </div> <h3>❌ Esempio che VIOLA la 3NF</h3> <p>Tabella "Impiegati" in 2NF ma con dipendenza transitiva.</p> <table> <tr><th>ID_Impiegato</th><th>Nome</th><th>ID_Ufficio</th><th>Città_Ufficio</th></tr> <tr><td style="text-align: center">10</td><td>Anna</td><td>U1</td><td>Roma</td></tr> <tr><td style="text-align: center">11</td><td>Luigi</td><td>U2</td><td>Milano</td></tr> <tr><td style="text-align: center">12</td><td>Sofia</td><td>U1</td><td>Roma</td></tr> </table> <p><strong>⚠️ Problema:</strong> "Città_Ufficio" dipende da "ID_Ufficio" (attributo non chiave), non direttamente da ID_Impiegato. Esiste una <strong>dipendenza transitiva</strong>:<br> <code>ID_Impiegato → ID_Ufficio → Città_Ufficio</code>.<br> Ridondanza: "Roma" ripetuta per ogni impiegato dello stesso ufficio.</p> <p><strong>Anomalie:</strong> se un ufficio cambia città, bisogna aggiornare tutte le righe degli impiegati (rischio inconsistenza).</p> <h3>✅ Soluzione: scomposizione in 3NF</h3> <p>Separare la dipendenza transitiva in una tabella dedicata agli uffici.</p> <p><strong>📋 Tabella IMPIEGATI (3NF)</strong></p> <table> <tr><th>ID_Impiegato (PK)</th><th>Nome</th><th>ID_Ufficio (FK)</th></tr> <tr><td style="text-align: center">10</td><td>Anna</td><td>U1</td></tr> <tr><td style="text-align: center">11</td><td>Luigi</td><td>U2</td></tr> <tr><td style="text-align: center">12</td><td>Sofia</td><td>U1</td></tr> </table> <p><strong>📋 Tabella UFFICI</strong></p> <table> <tr><th>ID_Ufficio (PK)</th><th>Città_Ufficio</th></tr> <tr><td style="text-align: center">U1</td><td>Roma</td></tr> <tr><td style="text-align: center">U2</td><td>Milano</td></tr> </table> <div class="correct"> <strong>✅ Risultato:</strong> 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. </div> <!-- Immagine 3: Diagramma 3NF --> <div class="image-container"> <img src="immagine3.jpg" alt="Diagramma 3NF - eliminazione dipendenze transitive" onerror="this.style.display='none'"> <div class="caption">Figura 3: Eliminazione della dipendenza transitiva separando la tabella Uffici</div> </div> <!-- Immagine 4: Diagramma riepilogativo --> <div class="image-container"> <img src="immagine4.jpg" alt="Diagramma riepilogativo delle 3 forme normali" onerror="this.style.display='none'"> <div class="caption">Figura 4: Riepilogo visivo dei tre passaggi di normalizzazione</div> </div> <!-- ============================================= --> <!-- RIEPILOGO FINALE --> <!-- ============================================= --> <h2>📊 Riepilogo comparativo</h2> <table class="summary-table"> <tr><th>Forma normale</th><th>Regola chiave</th><th>Problema risolto</th><th>Quando applicare</th></tr> <tr><td style="text-align: center"><strong>1NF</strong></td><td>Attributi atomici + chiave univoca</td><td>Dati multivalore, gruppi ripetuti</td><td>Sempre</td></tr> <tr><td style="text-align: center"><strong>2NF</strong></td><td>Nessuna dipendenza parziale</td><td>Ridondanza in chiave composta</td><td>Con chiavi primarie composte</td></tr> <tr><td style="text-align: center"><strong>3NF</strong></td><td>Nessuna dipendenza transitiva</td><td>Ridondanza tra attributi non chiave</td><td>Quasi sempre (fino a 3NF è standard)</td></tr> </table> <h2>🎯 Conclusione:</h2> <ul> <li>La normalizzazione fino alla <strong>3NF</strong> è sufficiente per la maggior parte dei database relazionali.</li> <li>Riduce la ridondanza, migliora l'integrità dei dati e semplifica la manutenzione.</li> <li>Forme superiori (BCNF, 4NF, 5NF) esistono ma sono usate raramente nella pratica quotidiana.</li> </ul> <hr> <!-- ============================================= --> <!-- ESERCIZI DI NORMALIZZAZIONE --> <!-- ============================================= --> <h2>📝 ESERCIZI: Normalizza tu stesso!</h2> <p>Di seguito trovi 4 esercizi di difficoltà crescente. Prova a normalizzare i dati fino alla 3NF, poi confronta con la soluzione.</p> <hr> <!-- ESERCIZIO 1 --> <h3>✏️ Esercizio 1 - Raggiungi la 1NF</h3> <p><strong>Consegna:</strong> La tabella "Libri" memorizza informazioni sui libri e i loro autori. Normalizza in 1NF.</p> <h4>Tabella di partenza (viola 1NF):</h4> <table> <tr><th>ID_Libro</th><th>Titolo</th><th>Autori</th><th>Anno</th></tr> <tr><td style="text-align: center">1</td><td>Database Facile</td><td>Rossi, Bianchi</td><td style="text-align: center">2020</td></tr> <tr><td style="text-align: center">2</td><td>SQL Avanzato</td><td>Verdi</td><td style="text-align: center">2021</td></tr> <tr><td style="text-align: center">3</td><td>NoSQL Guida</td><td>Neri, Rossi, Gialli</td><td style="text-align: center">2022</td></tr> </table> <details> <summary><strong>🔍 Mostra soluzione Esercizio 1 (1NF)</strong></summary> <div class="correct" style="margin-top: 15px;"> <p><strong>Soluzione:</strong> Scomporre gli autori su righe separate. Chiave primaria composta (ID_Libro, Autore).</p> <table> <tr><th>ID_Libro</th><th>Titolo</th><th>Autore</th><th>Anno</th></tr> <tr><td style="text-align: center">1</td><td>Database Facile</td><td>Rossi</td><td style="text-align: center">2020</td></tr> <tr><td style="text-align: center">1</td><td>Database Facile</td><td>Bianchi</td><td style="text-align: center">2020</td></tr> <tr><td style="text-align: center">2</td><td>SQL Avanzato</td><td>Verdi</td><td style="text-align: center">2021</td></tr> <tr><td style="text-align: center">3</td><td>NoSQL Guida</td><td>Neri</td><td style="text-align: center">2022</td></tr> <tr><td style="text-align: center">3</td><td>NoSQL Guida</td><td>Rossi</td><td style="text-align: center">2022</td></tr> <tr><td style="text-align: center">3</td><td>NoSQL Guida</td><td>Gialli</td><td style="text-align: center">2022</td></tr> </table> <p>✅ Ora ogni cella contiene un valore atomico.</p> </div> </details> <hr> <!-- ESERCIZIO 2 --> <h3>✏️ Esercizio 2 - Raggiungi la 2NF</h3> <p><strong>Consegna:</strong> La tabella "OrdiniClienti" ha chiave primaria composta (ID_Ordine, ID_Prodotto). Normalizza in 2NF.</p> <h4>Tabella di partenza (in 1NF ma viola 2NF):</h4> <table> <tr><th>ID_Ordine</th><th>ID_Prodotto</th><th>Data_Ordine</th><th>Nome_Cliente</th><th>Prodotto_Nome</th><th>Quantità</th></tr> <tr><td style="text-align: center">101</td><td style="text-align: center">P1</td><td>2025-01-10</td><td>Marco</td><td>Mouse</td><td style="text-align: center">2</td></tr> <tr><td style="text-align: center">101</td><td style="text-align: center">P2</td><td>2025-01-10</td><td>Marco</td><td>Tastiera</td><td style="text-align: center">1</td></tr> <tr><td style="text-align: center">102</td><td style="text-align: center">P1</td><td>2025-01-11</td><td>Laura</td><td>Mouse</td><td style="text-align: center">3</td></tr> </table> <details> <summary><strong>🔍 Mostra soluzione Esercizio 2 (2NF)</strong></summary> <div class="correct" style="margin-top: 15px;"> <p><strong>Soluzione:</strong> Identificare le dipendenze parziali: Data_Ordine e Nome_Cliente dipendono solo da ID_Ordine. Prodotto_Nome dipende solo da ID_Prodotto. Creare 3 tabelle.</p> <p><strong>Tabella ORDINI:</strong></p> <table> <tr><th>ID_Ordine (PK)</th><th>Data_Ordine</th><th>Nome_Cliente</th></tr> <tr><td style="text-align: center">101</td><td>2025-01-10</td><td>Marco</td></tr> <tr><td style="text-align: center">102</td><td>2025-01-11</td><td>Laura</td></tr> </table> <p><strong>Tabella PRODOTTI:</strong></p> <table> <tr><th>ID_Prodotto (PK)</th><th>Prodotto_Nome</th></tr> <tr><td style="text-align: center">P1</td><td>Mouse</td></tr> <tr><td style="text-align: center">P2</td><td>Tastiera</td></tr> </table> <p><strong>Tabella DETTAGLI_ORDINE (tabella ponte):</strong></p> <table> <tr><th>ID_Ordine (FK)</th><th>ID_Prodotto (FK)</th><th>Quantità</th></tr> <tr><td style="text-align: center">101</td><td style="text-align: center">P1</td><td style="text-align: center">2</td></tr> <tr><td style="text-align: center">101</td><td style="text-align: center">P2</td><td style="text-align: center">1</td></tr> <tr><td style="text-align: center">102</td><td style="text-align: center">P1</td><td style="text-align: center">3</td></tr> </table> <p>✅ Eliminate tutte le dipendenze parziali.</p> </div> </details> <hr> <!-- ESERCIZIO 3 --> <h3>✏️ Esercizio 3 - Raggiungi la 3NF</h3> <p><strong>Consegna:</strong> La tabella "ProgettiDipendenti" è già in 2NF, ma ha una dipendenza transitiva. Normalizza in 3NF.</p> <h4>Tabella di partenza (in 2NF, viola 3NF):</h4> <table> <tr><th>ID_Dipendente</th><th>Nome_Dipendente</th><th>ID_Progetto</th><th>Nome_Progetto</th><th>Reparto</th><th>Edificio_Reparto</th></tr> <tr><td style="text-align: center">D1</td><td>Anna</td><td style="text-align: center">PRJ1</td><td>AI</td><td>R&amp;D</td><td>Edificio A</td></tr> <tr><td style="text-align: center">D2</td><td>Luigi</td><td style="text-align: center">PRJ1</td><td>AI</td><td>R&amp;D</td><td>Edificio A</td></tr> <tr><td style="text-align: center">D3</td><td>Sofia</td><td style="text-align: center">PRJ2</td><td>Cloud</td><td>Infrastrutture</td><td>Edificio B</td></tr> </table> <p><strong>Suggerimento:</strong> Individua la dipendenza transitiva: ID_Dipendente → ? ?</p> <details> <summary><strong>🔍 Mostra soluzione Esercizio 3 (3NF)</strong></summary> <div class="correct" style="margin-top: 15px;"> <p><strong>Soluzione:</strong> Dipendenza transitiva: ID_Dipendente → Reparto → Edificio_Reparto. Inoltre Nome_Progetto dipende da ID_Progetto (altro attributo non chiave).</p> <p><strong>Tabella DIPENDENTI_PROGETTI (relazione pura):</strong></p> <table> <tr><th>ID_Dipendente</th><th>ID_Progetto</th></tr> <tr><td style="text-align: center">D1</td><td style="text-align: center">PRJ1</td></tr> <tr><td style="text-align: center">D2</td><td style="text-align: center">PRJ1</td></tr> <tr><td style="text-align: center">D3</td><td style="text-align: center">PRJ2</td></tr> </table> <p><strong>Tabella DIPENDENTI:</strong></p> <table> <tr><th>ID_Dipendente (PK)</th><th>Nome_Dipendente</th><th>Reparto</th></tr> <tr><td style="text-align: center">D1</td><td>Anna</td><td>R&amp;D</td></tr> <tr><td style="text-align: center">D2</td><td>Luigi</td><td>R&amp;D</td></tr> <tr><td style="text-align: center">D3</td><td>Sofia</td><td>Infrastrutture</td></tr> </table> <p><strong>Tabella REPARTI:</strong></p> <table> <tr><th>Reparto (PK)</th><th>Edificio_Reparto</th></tr> <tr><td>R&amp;D</td><td>Edificio A</td></tr> <tr><td>Infrastrutture</td><td>Edificio B</td></tr> </table> <p><strong>Tabella PROGETTI:</strong></p> <table> <tr><th>ID_Progetto (PK)</th><th>Nome_Progetto</th></tr> <tr><td style="text-align: center">PRJ1</td><td>AI</td></tr> <tr><td style="text-align: center">PRJ2</td><td>Cloud</td></tr> </table> <p>✅ Eliminate tutte le dipendenze transitive.</p> </div> </details> <hr> <!-- ESERCIZIO 4 - COMPLETO --> <h3>✏️ Esercizio 4 - Sfida completa (1NF → 2NF → 3NF)</h3> <p><strong>Consegna:</strong> La tabella "CorsiStudentiDocenti" riassume corsi, studenti e docenti. Normalizza completamente fino alla 3NF.</p> <h4>Tabella di partenza (non normalizzata):</h4> <table> <tr><th>ID_Corso</th><th>Nome_Corso</th><th>Studenti (lista)</th><th>ID_Docente</th><th>Nome_Docente</th><th>Specializzazione_Docente</th></tr> <tr><td style="text-align: center">CS101</td><td>Database</td><td>Marco, Laura</td><td style="text-align: center">D10</td><td>Rossi</td><td>SQL, NoSQL</td></tr> <tr><td style="text-align: center">CS102</td><td>Python</td><td>Marco, Sofia, Luigi</td><td style="text-align: center">D20</td><td>Bianchi</td><td>Python, Django</td></tr> <tr><td style="text-align: center">CS101</td><td>Database</td><td>Sofia</td><td style="text-align: center">D10</td><td>Rossi</td><td>SQL, NoSQL</td></tr> </table> <details> <summary><strong>🔍 Mostra soluzione Esercizio 4 (3NF completa)</strong></summary> <div class="correct" style="margin-top: 15px;"> <p><strong>Soluzione passo passo:</strong></p> <ol> <li><strong>1NF:</strong> Scomporre studenti e specializzazioni in righe atomiche.</li> <li><strong>2NF:</strong> Identificare dipendenze parziali (Nome_Corso dipende solo da ID_Corso).</li> <li><strong>3NF:</strong> Eliminare dipendenze transitive (Specializzazione_Docente dipende da ID_Docente).</li> </ol> <p><strong>Tabella CORSI:</strong></p> <table> <tr><th>ID_Corso (PK)</th><th>Nome_Corso</th></tr> <tr><td style="text-align: center">CS101</td><td>Database</td></tr> <tr><td style="text-align: center">CS102</td><td>Python</td></tr> </table> <p><strong>Tabella DOCENTI:</strong></p> <table> <tr><th>ID_Docente (PK)</th><th>Nome_Docente</th></tr> <tr><td style="text-align: center">D10</td><td>Rossi</td></tr> <tr><td style="text-align: center">D20</td><td>Bianchi</td></tr> </table> <p><strong>Tabella SPECIALIZZAZIONI_DOCENTE (1NF per le specializzazioni):</strong></p> <table> <tr><th>ID_Docente (FK)</th><th>Specializzazione</th></tr> <tr><td style="text-align: center">D10</td><td>SQL</td></tr> <tr><td style="text-align: center">D10</td><td>NoSQL</td></tr> <tr><td style="text-align: center">D20</td><td>Python</td></tr> <tr><td style="text-align: center">D20</td><td>Django</td></tr> </table> <p><strong>Tabella STUDENTI (dall'estrazione degli studenti unici):</strong></p> <table> <tr><th>ID_Studente (generato)</th><th>Nome_Studente</th></tr> <tr><td style="text-align: center">S1</td><td>Marco</td></tr> <tr><td style="text-align: center">S2</td><td>Laura</td></tr> <tr><td style="text-align: center">S3</td><td>Sofia</td></tr> <tr><td style="text-align: center">S4</td><td>Luigi</td></tr> </table> <p><strong>Tabella ISCRIZIONI_CORSI (relazione studenti-corsi):</strong></p> <table> <tr><th>ID_Studente (FK)</th><th>ID_Corso (FK)</th></tr> <tr><td style="text-align: center">S1</td><td style="text-align: center">CS101</td></tr> <tr><td style="text-align: center">S2</td><td style="text-align: center">CS101</td></tr> <tr><td style="text-align: center">S1</td><td style="text-align: center">CS102</td></tr> <tr><td style="text-align: center">S3</td><td style="text-align: center">CS102</td></tr> <tr><td style="text-align: center">S4</td><td style="text-align: center">CS102</td></tr> <tr><td style="text-align: center">S3</td><td style="text-align: center">CS101</td></tr> </table> <p><strong>Tabella ASSEGNAZIONE_DOCENTI (un corso può avere un docente):</strong></p> <table> <tr><th>ID_Corso (FK)</th><th>ID_Docente (FK)</th></tr> <tr><td style="text-align: center">CS101</td><td style="text-align: center">D10</td></tr> <tr><td style="text-align: center">CS102</td><td style="text-align: center">D20</td></tr> </table> <p>✅ Database completamente normalizzato in 3NF, senza ridondanze né anomalie.</p> </div> </details> <hr> <!-- RIEPILOGO ESERCIZI --> <h3>📌 Autovalutazione</h3> <p>Dopo aver completato gli esercizi, verifica di aver compreso:</p> <ul> <li>✅ Riconoscere valori non atomici (violazione 1NF)</li> <li>✅ Identificare dipendenze parziali in chiavi composte (violazione 2NF)</li> <li>✅ Scovare dipendenze transitive tra attributi non chiave (violazione 3NF)</li> <li>✅ Applicare la scomposizione in sottotabelle senza perdita di informazioni</li> </ul> <div class="rule-box"> <strong>💡 Suggerimento finale:</strong> Per verificare se hai normalizzato correttamente, controlla che:<br> - Ogni tabella rappresenti un <strong>unico concetto</strong> (entità).<br> - Tutti gli attributi non chiave descrivano <strong>completamente</strong> la chiave primaria (e solo quella).<br> - Non ci siano <strong>catene di dipendenze</strong> tra attributi non chiave. </div> <hr> <p><em>📚 Esercizi tratti da casi reali - Prova a inventare nuovi esempi dalla tua esperienza per allenarti ulteriormente!</em></p> </body> </html>
///(Fine file: TutorialFormeNormali2026-CON-SOLUZIONE-ESERCIZI.html)

///File: TutorialFormeNormali2026.html
<!DOCTYPE html> <html lang="it"> <head> <meta charset="UTF-8"> <title>Tutorial Normalizzazione Database - 1NF, 2NF, 3NF - F. Sacco - Maggio 2026</title> <style> body { font-family: Arial, sans-serif; margin: 2cm; line-height: 1.4; max-width: 1200px; margin-left: auto; margin-right: auto; } h1 { color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 5px; } h2 { color: #2980b9; margin-top: 35px; border-left: 5px solid #3498db; padding-left: 15px; } h3 { color: #16a085; margin-top: 25px; } table { border-collapse: collapse; width: 100%; margin: 20px 0; background: #f9f9f9; box-shadow: 0 1px 3px rgba(0,0,0,0.1); } th, td { border: 1px solid #aaa; padding: 10px; text-align: left; vertical-align: top; } th { background: #ecf0f1; font-weight: bold; } .wrong { border-left: 5px solid #e74c3c; padding-left: 15px; background: #fceaea; margin: 15px 0; } .correct { border-left: 5px solid #2ecc71; padding-left: 15px; background: #e8f8f5; margin: 15px 0; } .image-container { text-align: center; margin: 25px 0; background: #fef9e7; padding: 15px; border-radius: 8px; border: 1px solid #f39c12; } .image-container img { max-width: 100%; height: auto; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .image-container .caption { font-style: italic; margin-top: 10px; color: #7f8c8d; font-size: 0.9em; } .rule-box { background: #e8f8f5; padding: 15px; border-radius: 8px; margin: 20px 0; border-left: 5px solid #1abc9c; } .summary-table { background: #ecf0f1; } .salto-pagina { page-break-before: always; } hr { margin: 40px 0; border: 1px solid #bdc3c7; } </style> </head> <body> <h1>📘 Tutorial completo: Normalizzazione nei database</h1> <p>La normalizzazione elimina ridondanze e anomalie di inserimento, cancellazione e aggiornamento. Vediamo le <strong>tre forme normali (1NF, 2NF, 3NF)</strong> con esempi reali e diagrammi illustrativi.</p> <!-- ============================================= --> <!-- PRIMA FORMA NORMALE --> <!-- ============================================= --> <h2>🔹 1. Prima Forma Normale (1NF)</h2> <div class="rule-box"> <strong>📌 Regole della 1NF:</strong> <ul> <li>Ogni colonna deve contenere valori <strong>atomici</strong> (indivisibili).</li> <li>Non sono ammesse ripetizioni di gruppi di colonne (es. Telefono1, Telefono2).</li> <li>Ogni riga deve essere univocamente identificabile (chiave primaria).</li> </ul> </div> <h3>❌ Esempio che VIOLA la 1NF</h3> <p>Tabella "Studenti" con numeri di telefono multipli nella stessa cella e attributi ripetuti.</p> <table> <tr><th>ID Studente</th><th>Nome</th><th>Telefoni</th><th>Telefono2</th></tr> <tr><td style="text-align: center">1</td><td>Marco Rossi</td><td>331123456, 331654321</td><td>NULL</td></tr> <tr><td style="text-align: center">2</td><td>Laura Bianchi</td><td>392111222</td><td>392333444</td></tr> </table> <p><strong>⚠️ Problemi:</strong> I telefoni non sono atomici (nel primo caso ci sono due numeri separati da virgola). Colonne Telefono1/Telefono2 creano ridondanza e difficoltà di ricerca.</p> <h3>✅ Esempio CORRETTO in 1NF</h3> <p>Suddivido i telefoni su righe distinte e creo una chiave primaria composta (ID_Studente, Telefono).</p> <table> <tr><th>ID Studente</th><th>Nome</th><th>Telefono</th></tr> <tr><td style="text-align: center">1</td><td>Marco Rossi</td><td>331123456</td></tr> <tr><td style="text-align: center">1</td><td>Marco Rossi</td><td>331654321</td></tr> <tr><td style="text-align: center">2</td><td>Laura Bianchi</td><td>392111222</td></tr> <tr><td style="text-align: center">2</td><td>Laura Bianchi</td><td>392333444</td></tr> </table> <div class="correct"> <strong>✅ Risultato:</strong> Ora ogni attributo è atomico e non esistono gruppi ripetuti. Ogni riga è univoca grazie alla coppia (ID_Studente, Telefono). </div> <!-- Immagine 1: Diagramma 1NF --> <div class="image-container"> <img src="immagine1.jpg" alt="Diagramma 1NF - da valori multipli ad atomici" onerror="this.style.display='none'"> <div class="caption">Figura 1: Trasformazione dalla violazione della 1NF alla corretta 1NF</div> </div> <!-- ============================================= --> <!-- SECONDA FORMA NORMALE --> <!-- ============================================= --> <h2>🔸 2. Seconda Forma Normale (2NF)</h2> <div class="rule-box"> <strong>📌 Regole della 2NF:</strong> <ul> <li>La tabella deve essere già in 1NF.</li> <li><strong>Nessuna dipendenza parziale</strong> dalla chiave primaria: ogni colonna non chiave deve dipendere dall'<em>intera</em> chiave primaria (non solo da una parte).</li> </ul> <em>Nota: la 2NF ha senso solo con chiavi primarie composte.</em> </div> <h3>❌ Esempio che VIOLA la 2NF</h3> <p>Tabella "IscrizioniCorsi" con chiave primaria composta (ID_Studente, ID_Corso).</p> <table> <tr><th>ID_Studente</th><th>ID_Corso</th><th>Nome_Studente</th><th>Nome_Corso</th><th>Data_Iscrizione</th></tr> <tr><td style="text-align: center">1</td><td style="text-align: center">101</td><td>Marco</td><td>Matematica</td><td>2025-01-10</td></tr> <tr><td style="text-align: center">1</td><td style="text-align: center">102</td><td>Marco</td><td>Fisica</td><td>2025-01-12</td></tr> <tr><td style="text-align: center">2</td><td style="text-align: center">101</td><td>Laura</td><td>Matematica</td><td>2025-01-11</td></tr> </table> <p><strong>⚠️ Problema:</strong> "Nome_Studente" dipende solo da ID_Studente (non da ID_Corso), e "Nome_Corso" dipende solo da ID_Corso. Sono <strong>dipendenze parziali</strong> → violazione 2NF. Ridondanza: "Marco" e "Matematica" vengono ripetuti più volte.</p> <h3>✅ Soluzione: scomposizione in 2NF</h3> <p>Creo tre tabelle separate, eliminando ogni dipendenza parziale:</p> <p><strong>📋 Tabella STUDENTI</strong></p> <table> <tr><th>ID_Studente (PK)</th><th>Nome_Studente</th><tr> <tr><td style="text-align: center">1</td><td>Marco</td></tr> <tr><td style="text-align: center">2</td><td>Laura</td></tr> </table> <p><strong>📋 Tabella CORSI</strong></p> <table> <tr><th>ID_Corso (PK)</th><th>Nome_Corso</th></tr> <tr><td style="text-align: center">101</td><td>Matematica</td></tr> <tr><td style="text-align: center">102</td><td>Fisica</td></tr> </table> <p><strong>📋 Tabella ISCRIZIONI (tabella ponte)</strong></p> <table> <tr><th>ID_Studente (FK)</th><th>ID_Corso (FK)</th><th>Data_Iscrizione</th></tr> <tr><td style="text-align: center">1</td><td style="text-align: center">101</td><td>2025-01-10</td></tr> <tr><td style="text-align: center">1</td><td style="text-align: center">102</td><td>2025-01-12</td></tr> <tr><td style="text-align: center">2</td><td style="text-align: center">101</td><td>2025-01-11</td></tr> </table> <div class="correct"> <strong>✅ Risultato:</strong> Ora ogni attributo non chiave dipende dall'intera chiave primaria della propria tabella. Nessuna ridondanza. </div> <!-- Immagine 2: Diagramma 2NF --> <div class="image-container"> <img src="immagine2.jpg" alt="Diagramma 2NF - eliminazione dipendenze parziali" onerror="this.style.display='none'"> <div class="caption">Figura 2: Scomposizione per eliminare le dipendenze parziali dalla chiave composta</div> </div> <!-- ============================================= --> <!-- TERZA FORMA NORMALE --> <!-- ============================================= --> <h2>🔹 3. Terza Forma Normale (3NF)</h2> <div class="rule-box"> <strong>📌 Regole della 3NF:</strong> <ul> <li>La tabella deve essere già in 2NF.</li> <li><strong>Nessuna dipendenza transitiva</strong>: un attributo non chiave non può dipendere da un altro attributo non chiave.</li> </ul> </div> <h3>❌ Esempio che VIOLA la 3NF</h3> <p>Tabella "Impiegati" in 2NF ma con dipendenza transitiva.</p> <table> <tr><th>ID_Impiegato</th><th>Nome</th><th>ID_Ufficio</th><th>Città_Ufficio</th></tr> <tr><td style="text-align: center">10</td><td>Anna</td><td>U1</td><td>Roma</td></tr> <tr><td style="text-align: center">11</td><td>Luigi</td><td>U2</td><td>Milano</td></tr> <tr><td style="text-align: center">12</td><td>Sofia</td><td>U1</td><td>Roma</td></tr> </table> <p><strong>⚠️ Problema:</strong> "Città_Ufficio" dipende da "ID_Ufficio" (attributo non chiave), non direttamente da ID_Impiegato. Esiste una <strong>dipendenza transitiva</strong>:<br> <code>ID_Impiegato → ID_Ufficio → Città_Ufficio</code>.<br> Ridondanza: "Roma" ripetuta per ogni impiegato dello stesso ufficio.</p> <p><strong>Anomalie:</strong> se un ufficio cambia città, bisogna aggiornare tutte le righe degli impiegati (rischio inconsistenza).</p> <h3>✅ Soluzione: scomposizione in 3NF</h3> <p>Separare la dipendenza transitiva in una tabella dedicata agli uffici.</p> <p><strong>📋 Tabella IMPIEGATI (3NF)</strong></p> <table> <tr><th>ID_Impiegato (PK)</th><th>Nome</th><th>ID_Ufficio (FK)</th></tr> <tr><td style="text-align: center">10</td><td>Anna</td><td>U1</td></tr> <tr><td style="text-align: center">11</td><td>Luigi</td><td>U2</td></tr> <tr><td style="text-align: center">12</td><td>Sofia</td><td>U1</td></tr> </table> <p><strong>📋 Tabella UFFICI</strong></p> <table> <tr><th>ID_Ufficio (PK)</th><th>Città_Ufficio</th></tr> <tr><td style="text-align: center">U1</td><td>Roma</td></tr> <tr><td style="text-align: center">U2</td><td>Milano</td></tr> </table> <div class="correct"> <strong>✅ Risultato:</strong> 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. </div> <!-- Immagine 3: Diagramma 3NF --> <div class="image-container"> <img src="immagine3.jpg" alt="Diagramma 3NF - eliminazione dipendenze transitive" onerror="this.style.display='none'"> <div class="caption">Figura 3: Eliminazione della dipendenza transitiva separando la tabella Uffici</div> </div> <!-- Immagine 4: Diagramma riepilogativo --> <div class="image-container"> <img src="immagine4.jpg" alt="Diagramma riepilogativo delle 3 forme normali" onerror="this.style.display='none'"> <div class="caption">Figura 4: Riepilogo visivo dei tre passaggi di normalizzazione</div> </div> <!-- ============================================= --> <!-- RIEPILOGO FINALE --> <!-- ============================================= --> <h2>📊 Riepilogo comparativo</h2> <table class="summary-table"> <tr><th>Forma normale</th><th>Regola chiave</th><th>Problema risolto</th><th>Quando applicare</th></tr> <tr><td style="text-align: center"><strong>1NF</strong></td><td>Attributi atomici + chiave univoca</td><td>Dati multivalore, gruppi ripetuti</td><td>Sempre</td></tr> <tr><td style="text-align: center"><strong>2NF</strong></td><td>Nessuna dipendenza parziale</td><td>Ridondanza in chiave composta</td><td>Con chiavi primarie composte</td></tr> <tr><td style="text-align: center"><strong>3NF</strong></td><td>Nessuna dipendenza transitiva</td><td>Ridondanza tra attributi non chiave</td><td>Quasi sempre (fino a 3NF è standard)</td></tr> </table> <h2>🎯 Conclusione:</h2> <ul> <li>La normalizzazione fino alla <strong>3NF</strong> è sufficiente per la maggior parte dei database relazionali.</li> <li>Riduce la ridondanza, migliora l'integrità dei dati e semplifica la manutenzione.</li> <li>Forme superiori (BCNF, 4NF, 5NF) esistono ma sono usate raramente nella pratica quotidiana.</li> </ul> <!-- ============================================= --> <!-- ESERCIZI DI NORMALIZZAZIONE --> <!-- ============================================= --> <h2>📝 ESERCIZI: Normalizza tu stesso!</h2> <p>Di seguito trovi 4 esercizi di difficoltà crescente. Normalizza i dati fino alla 3NF su un foglio a parte. Le soluzioni possono essere fornite dal docente o verificate successivamente.</p> <hr> <!-- ESERCIZIO 1 --> <h3>✏️ Esercizio 1 - Raggiungi la 1NF</h3> <p><strong>Consegna:</strong> La tabella "Libri" memorizza informazioni sui libri e i loro autori. Normalizza in 1NF.</p> <h4>Tabella di partenza (viola 1NF):</h4> <table> <tr><th>ID_Libro</th><th>Titolo</th><th>Autori</th><th>Anno</th></tr> <tr><td style="text-align: center">1</td><td>Database Facile</td><td>Rossi, Bianchi</td><td style="text-align: center">2020</td></tr> <tr><td style="text-align: center">2</td><td>SQL Avanzato</td><td>Verdi</td><td style="text-align: center">2021</td></tr> <tr><td style="text-align: center">3</td><td>NoSQL Guida</td><td>Neri, Rossi, Gialli</td><td style="text-align: center">2022</td></tr> </table> <hr> <!-- ESERCIZIO 2 --> <h3>✏️ Esercizio 2 - Raggiungi la 2NF</h3> <p><strong>Consegna:</strong> La tabella "OrdiniClienti" ha chiave primaria composta (ID_Ordine, ID_Prodotto). Normalizza in 2NF.</p> <h4>Tabella di partenza (in 1NF ma viola 2NF):</h4> <table> <tr><th>ID_Ordine</th><th>ID_Prodotto</th><th>Data_Ordine</th><th>Nome_Cliente</th><th>Prodotto_Nome</th><th>Quantità</th></tr> <tr><td style="text-align: center">101</td><td style="text-align: center">P1</td><td>2025-01-10</td><td>Marco</td><td>Mouse</td><td style="text-align: center">2</td></tr> <tr><td style="text-align: center">101</td><td style="text-align: center">P2</td><td>2025-01-10</td><td>Marco</td><td>Tastiera</td><td style="text-align: center">1</td></tr> <tr><td style="text-align: center">102</td><td style="text-align: center">P1</td><td>2025-01-11</td><td>Laura</td><td>Mouse</td><td style="text-align: center">3</td></tr> </table> <hr> <!-- ESERCIZIO 3 --> <h3>✏️ Esercizio 3 - Raggiungi la 3NF</h3> <p><strong>Consegna:</strong> La tabella "ProgettiDipendenti" è già in 2NF, ma ha una dipendenza transitiva. Normalizza in 3NF.</p> <h4>Tabella di partenza (in 2NF, viola 3NF):</h4> <table> <tr><th>ID_Dipendente</th><th>Nome_Dipendente</th><th>ID_Progetto</th><th>Nome_Progetto</th><th>Reparto</th><th>Edificio_Reparto</th></tr> <tr><td style="text-align: center">D1</td><td>Anna</td><td style="text-align: center">PRJ1</td><td>AI</td><td>R&amp;D</td><td>Edificio A</td></tr> <tr><td style="text-align: center">D2</td><td>Luigi</td><td style="text-align: center">PRJ1</td><td>AI</td><td>R&amp;D</td><td>Edificio A</td></tr> <tr><td style="text-align: center">D3</td><td>Sofia</td><td style="text-align: center">PRJ2</td><td>Cloud</td><td>Infrastrutture</td><td>Edificio B</td></tr> </table> <p><strong>Suggerimento:</strong> Individua la dipendenza transitiva: ID_Dipendente → ? ?</p> <hr> <!-- ESERCIZIO 4 - COMPLETO --> <h3>✏️ Esercizio 4 - Sfida completa (1NF → 2NF → 3NF)</h3> <p><strong>Consegna:</strong> La tabella "CorsiStudentiDocenti" riassume corsi, studenti e docenti. Normalizza completamente fino alla 3NF.</p> <h4>Tabella di partenza (non normalizzata):</h4> <table> <tr><th>ID_Corso</th><th>Nome_Corso</th><th>Studenti (lista)</th><th>ID_Docente</th><th>Nome_Docente</th><th>Specializzazione_Docente</th></tr> <tr><td style="text-align: center">CS101</td><td>Database</td><td>Marco, Laura</td><td style="text-align: center">D10</td><td>Rossi</td><td>SQL, NoSQL</td></tr> <tr><td style="text-align: center">CS102</td><td>Python</td><td>Marco, Sofia, Luigi</td><td style="text-align: center">D20</td><td>Bianchi</td><td>Python, Django</td></tr> <tr><td style="text-align: center">CS101</td><td>Database</td><td>Sofia</td><td style="text-align: center">D10</td><td>Rossi</td><td>SQL, NoSQL</td></tr> </table> <hr> <!-- RIEPILOGO ESERCIZI --> <h3>📌 Autovalutazione</h3> <p>Dopo aver completato gli esercizi, verifica di aver compreso:</p> <ul> <li>✅ Riconoscere valori non atomici (violazione 1NF)</li> <li>✅ Identificare dipendenze parziali in chiavi composte (violazione 2NF)</li> <li>✅ Scovare dipendenze transitive tra attributi non chiave (violazione 3NF)</li> <li>✅ Applicare la scomposizione in sottotabelle senza perdita di informazioni</li> </ul> <div class="rule-box"> <strong>💡 Suggerimento finale:</strong> Per verificare se hai normalizzato correttamente, controlla che:<br> - Ogni tabella rappresenti un <strong>unico concetto</strong> (entità).<br> - Tutti gli attributi non chiave descrivano <strong>completamente</strong> la chiave primaria (e solo quella).<br> - Non ci siano <strong>catene di dipendenze</strong> tra attributi non chiave. </div> <hr> <p><em>📚 Esercizi tratti da casi reali - Prova a inventare nuovi esempi dalla tua esperienza per allenarti ulteriormente.</em></p> </body> </html>
///(Fine file: TutorialFormeNormali2026.html)