Nei sistemi relazionali i dati sono organizzati in tabelle (chiamate anche relazioni). Ogni tabella rappresenta un’entità del mondo reale — clienti, ordini, prodotti — e ne descrive le caratteristiche in modo strutturato. È il modello alla base di database come Azure SQL Database, Azure Database for PostgreSQL e Azure Database for MySQL, ed è pensato per dati con uno schema fisso e definito in anticipo.
Tabelle, righe e colonne
Una tabella è una griglia bidimensionale composta da:
- Colonne (o attributi): definiscono quali informazioni memorizziamo e il loro tipo di dato (testo, numero intero, data, booleano). Lo schema delle colonne è fisso per tutta la tabella.
- Righe (o record/tuple): rappresentano una singola istanza dell’entità, ad esempio un cliente specifico. Ogni riga contiene un valore per ogni colonna.
Un principio fondamentale è che ogni colonna dovrebbe contenere un valore atomico (indivisibile): un singolo dato, non una lista. Questo rende i dati facili da interrogare con SQL (Structured Query Language), il linguaggio standard per leggere e scrivere nei database relazionali.
Chiavi primarie ed esterne
Le chiavi garantiscono l’identità dei dati e le relazioni tra tabelle.
- La chiave primaria (primary key) identifica in modo univoco ogni riga di una tabella. Non può essere duplicata né nulla. Ad esempio
CustomerIDin una tabella Clienti. - La chiave esterna (foreign key) è una colonna che fa riferimento alla chiave primaria di un’altra tabella, creando un collegamento logico. Nella tabella Ordini, la colonna
CustomerIDè una foreign key che indica quale cliente ha effettuato l’ordine.
Questo meccanismo assicura l’integrità referenziale: non è possibile inserire un ordine per un cliente inesistente. È così che il modello relazionale collega entità distinte senza duplicare i dati.
Normalizzazione: eliminare la ridondanza
La normalizzazione è il processo di progettazione delle tabelle per ridurre la ridondanza e prevenire anomalie di aggiornamento. L’idea chiave è: ogni informazione deve essere memorizzata una sola volta.
Se salvassimo nome e indirizzo del cliente in ogni riga della tabella Ordini, un cambio di indirizzo richiederebbe l’aggiornamento di decine di righe, con rischio di incoerenze. La soluzione è separare le entità in tabelle distinte (Clienti, Ordini, Prodotti) e collegarle tramite chiavi. Un design normalizzato tipicamente:
- separa i dati in più tabelle correlate;
- evita di ripetere gli stessi valori in righe diverse;
- usa foreign key per ricostruire le informazioni tramite JOIN quando servono.
Il vantaggio è la coerenza; il costo è che leggere un dato completo richiede di unire più tabelle.
Indici e viste: oggetti di supporto
Oltre alle tabelle esistono oggetti che migliorano prestazioni e usabilità.
Indici (index)
Un indice è una struttura che velocizza la ricerca delle righe, un po’ come l’indice analitico di un libro. Senza indice, il database deve scorrere l’intera tabella; con un indice sulla colonna cercata, trova i dati molto più rapidamente. Gli indici accelerano le letture ma rallentano leggermente scritture e aggiornamenti, e occupano spazio: vanno quindi usati con criterio.
Viste (view)
Una vista è una query salvata che si comporta come una tabella virtuale. Non memorizza dati propri, ma presenta i risultati di una SELECT, spesso già combinando più tabelle con JOIN. Le viste servono a semplificare query complesse e a esporre solo un sottoinsieme di colonne.
Il legame con i workload transazionali (OLTP)
Il modello relazionale, con chiavi e normalizzazione, è ottimizzato per i workload OLTP (Online Transaction Processing): tante operazioni piccole, rapide e frequenti — inserimenti, aggiornamenti, letture puntuali — come su un sito e-commerce o un gestionale.
Il cuore dell’OLTP è la transazione, che rispetta le proprietà ACID:
- Atomicity: la transazione avviene tutta o per niente;
- Consistency: il database passa da uno stato valido a un altro valido;
- Isolation: transazioni concorrenti non si interferiscono;
- Durability: una volta confermata (commit), la modifica è permanente.
La normalizzazione supporta l’OLTP perché scritture su tabelle piccole e non ridondanti sono veloci e sicure.
Trappole tipiche d’esame
- Scenario: dati con struttura fissa, molte scritture piccole e frequenti (es. sistema ordini) → risposta giusta: database relazionale con workload OLTP, non un data warehouse (OLAP).
- Scenario: devi impedire l’inserimento di un ordine per un cliente inesistente → risposta giusta: una foreign key che impone l’integrità referenziale.
- Scenario: identificare in modo univoco ogni riga di una tabella → risposta giusta: la primary key (univoca e non nulla), non un semplice indice.
- Scenario: le query su una tabella grande sono lente in lettura → risposta giusta: creare un indice sulla colonna filtrata, non normalizzare ulteriormente.
- Scenario: obiettivo “eliminare i dati duplicati e ridondanti” nella progettazione → risposta giusta: normalizzazione (non denormalizzazione, tipica invece dei workload analitici).