Il modello relazionale
Il modello relazionale, introdotto da Edgar F. Codd nel 1970, organizza i dati in relazioni (tabelle) composte da tuple (righe) e attributi (colonne). Ogni relazione rappresenta un'entità del dominio applicativo e le relazioni tra entità sono espresse attraverso chiavi condivise.
I principali RDBMS (Relational Database Management System) utilizzati oggi sono MySQL, PostgreSQL, Microsoft SQL Server, Oracle Database e SQLite. Ciascuno implementa lo standard SQL con estensioni proprietarie, ma i concetti fondamentali restano universali.
"Un database relazionale ben progettato garantisce integrità dei dati, eliminazione delle ridondanze e facilità di interrogazione."
Tabelle, righe e colonne
Una tabella (o relazione) è una struttura bidimensionale dove:
- Ogni colonna (attributo) ha un nome univoco e un tipo di dato (INTEGER, VARCHAR, DATE, BOOLEAN, ecc.).
- Ogni riga (tupla) rappresenta un singolo record, ovvero un'istanza dell'entità.
- L'ordine delle righe non ha significato logico; l'ordine delle colonne è definito dallo schema ma non influisce sulle query.
CREATE TABLE studenti (
id INT PRIMARY KEY AUTO_INCREMENT,
nome VARCHAR(50) NOT NULL,
cognome VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
data_nascita DATE,
corso_id INT
);
Chiavi primarie ed esterne
La chiave primaria (PRIMARY KEY) identifica univocamente ogni riga di una tabella. Può essere un singolo campo o una combinazione di più campi (chiave composta). Non ammette valori NULL né duplicati.
La chiave esterna (FOREIGN KEY) crea un collegamento tra due tabelle, garantendo l'integrità referenziale: il valore nella tabella figlia deve corrispondere a un valore esistente nella tabella padre.
CREATE TABLE corsi (
id INT PRIMARY KEY AUTO_INCREMENT,
nome VARCHAR(100) NOT NULL,
crediti INT DEFAULT 6
);
ALTER TABLE studenti
ADD CONSTRAINT fk_corso
FOREIGN KEY (corso_id) REFERENCES corsi(id)
ON DELETE SET NULL
ON UPDATE CASCADE;
SQL fondamentale
Il linguaggio SQL (Structured Query Language) si divide in sottolinguaggi:
| Categoria | Comandi principali | Scopo |
|---|---|---|
| DDL (Data Definition) | CREATE, ALTER, DROP | Definire la struttura |
| DML (Data Manipulation) | SELECT, INSERT, UPDATE, DELETE | Manipolare i dati |
| DCL (Data Control) | GRANT, REVOKE | Gestire i permessi |
| TCL (Transaction Control) | BEGIN, COMMIT, ROLLBACK | Gestire le transazioni |
Ecco le quattro operazioni CRUD fondamentali:
-- CREATE (inserimento)
INSERT INTO studenti (nome, cognome, email, corso_id)
VALUES ('Marco', 'Rossi', 'marco.rossi@uni.it', 1);
-- READ (lettura)
SELECT nome, cognome, email
FROM studenti
WHERE corso_id = 1
ORDER BY cognome ASC;
-- UPDATE (aggiornamento)
UPDATE studenti
SET email = 'nuovo@uni.it'
WHERE id = 1;
-- DELETE (cancellazione)
DELETE FROM studenti
WHERE id = 1;
Le JOIN
Le JOIN combinano righe di due o più tabelle basandosi su una condizione di correlazione. Sono il cuore del modello relazionale.
- INNER JOIN: restituisce solo le righe con corrispondenza in entrambe le tabelle.
- LEFT JOIN: restituisce tutte le righe della tabella sinistra, con NULL dove non c'è corrispondenza.
- RIGHT JOIN: simmetrico al LEFT JOIN.
- FULL OUTER JOIN: restituisce tutte le righe di entrambe le tabelle.
- CROSS JOIN: produce il prodotto cartesiano.
SELECT s.nome, s.cognome, c.nome AS corso
FROM studenti s
INNER JOIN corsi c ON s.corso_id = c.id
WHERE c.crediti >= 6
ORDER BY s.cognome;
Normalizzazione (1NF-3NF)
La normalizzazione è il processo di organizzazione delle tabelle per ridurre ridondanza e anomalie di inserimento, aggiornamento e cancellazione.
- Prima Forma Normale (1NF): ogni cella contiene un solo valore atomico; non ci sono gruppi ripetuti. Un campo "telefoni" con più numeri separati da virgola viola la 1NF.
- Seconda Forma Normale (2NF): soddisfa la 1NF e ogni attributo non-chiave dipende dall'intera chiave primaria (rilevante con chiavi composte).
- Terza Forma Normale (3NF): soddisfa la 2NF e nessun attributo non-chiave dipende transitivamente dalla chiave primaria. Se un campo "città" determina "regione", bisogna separare i dati in tabelle distinte.
"I dati devono dipendere dalla chiave, dalla chiave intera e da nient'altro che la chiave." — Regola mnemonica per la 3NF.
Indici
Un indice è una struttura dati (tipicamente un B-Tree o un hash) che accelera le operazioni di ricerca su una o più colonne, a fronte di un maggiore consumo di spazio e di un leggero rallentamento nelle operazioni di scrittura.
-- Indice su singola colonna
CREATE INDEX idx_email ON studenti(email);
-- Indice composto
CREATE INDEX idx_nome_cognome ON studenti(nome, cognome);
-- Indice univoco
CREATE UNIQUE INDEX idx_unique_email ON studenti(email);
Transazioni ACID
Le transazioni raggruppano più operazioni SQL in un'unità logica. Le proprietà ACID garantiscono la correttezza dei dati:
- Atomicità (Atomicity): la transazione viene eseguita completamente o per niente.
- Consistenza (Consistency): il database passa da uno stato valido a un altro stato valido.
- Isolamento (Isolation): le transazioni concorrenti non interferiscono tra loro.
- Durabilità (Durability): una volta confermata, la transazione sopravvive a guasti di sistema.
BEGIN TRANSACTION;
UPDATE conti SET saldo = saldo - 100 WHERE id = 1;
UPDATE conti SET saldo = saldo + 100 WHERE id = 2;
-- Se tutto ok:
COMMIT;
-- Se qualcosa va storto:
-- ROLLBACK;
Il classico esempio è il trasferimento bancario: se il prelievo va a buon fine ma l'accredito fallisce, il ROLLBACK annulla entrambe le operazioni, evitando incongruenze.
SQL vs NoSQL
I database relazionali eccellono quando i dati hanno una struttura ben definita e le relazioni tra entità sono importanti. Tuttavia, per scenari con dati semi-strutturati o esigenze di scalabilità orizzontale estrema, i database NoSQL possono essere più appropriati.
Per approfondire l'architettura di un'applicazione web completa, consulta anche la guida su API e Web Services e i fondamenti di JavaScript per la parte client-side.