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 CustomerID in 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).