Senza categoria

L’importanza di una storia: SQL e DB relazionali

Quando lavoriamo con i dati, stiamo raccontando una storia.
Clienti che acquistano prodotti. Studenti che sostengono esami. Conti che trasferiscono denaro.

Un database relazionale serve a mantenere questa storia ordinata, coerente e affidabile nel tempo.
SQL è il linguaggio con cui interroghiamo e modifichiamo quella storia.

Partiamo dalle fondamenta, poi saliamo gradualmente verso concetti più avanzati.


Il problema: organizzare il caos

Senza struttura, i dati si contraddicono:

  • Due utenti con la stessa email.
  • Un ordine senza cliente.
  • Informazioni duplicate in più punti.

Il caos non esplode subito. Si insinua lentamente.

Un database nasce per imporre ordine.


Tabelle: la struttura della storia

Un database relazionale organizza i dati in tabelle.

Ogni tabella è composta da:

  • Colonne (campi) → descrivono che tipo di informazione stiamo salvando.
  • Righe (record) → rappresentano i singoli elementi.

Esempio:

Tabella utenti

idnomeemail
1Paolopaolo@email.it
2Lucialucia@email.it

Ogni riga è un record.
Ogni colonna è un campo.


La chiave primaria: l’identità del record

Di solito troviamo qualcosa del genere:

id SERIAL PRIMARY KEY

La PRIMARY KEY (chiave primaria):

  • identifica ogni record in modo univoco
  • non può essere NULL
  • è il riferimento usato dalle altre tabelle

È la carta d’identità tecnica del record.

Può esistere una sola PRIMARY KEY per tabella legata per coerenza ad una o più FOREIGN KEY.

L’id è spesso un numero progressivo generato automaticamente.
È stabile, non cambia mai.


UNIQUE e NOT NULL: regole di coerenza

Ora introduciamo i vincoli.

NOT NULL

nome VARCHAR(100) NOT NULL

Significa: questo campo deve avere un valore.
NULL in SQL non è una stringa vuota. È “assenza di valore”. È “non sappiamo”.

NOT NULL impedisce l’assenza di dato.


UNIQUE

email VARCHAR(255) UNIQUE

Significa: nessuna email può comparire due volte.

Qui stiamo imponendo una regola di non duplicazione.


Differenza tra PRIMARY KEY (id) e UNIQUE

Qui c’è una distinzione importante.

Entrambi impediscono duplicati. Ma non sono la stessa cosa.

PRIMARY KEY:

  • definisce l’identità ufficiale del record
  • è unica per tabella
  • non può essere NULL
  • è usata nelle relazioni tra tabelle

UNIQUE:

  • impedisce duplicati su un campo
  • può esistere su più colonne
  • può essere usato solo come regola di validazione

Esempio:

id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
codice_fiscale VARCHAR(16) UNIQUE

Qui abbiamo:

  • un identificatore tecnico (id)
  • due campi che devono essere unici (email e codice fiscale)

Concettualmente:

  • La PRIMARY KEY dice chi è il record.
  • UNIQUE dice questa informazione non può ripetersi.

Un dettaglio interessante:
UNIQUE, nello standard SQL, permette più valori NULL (perché NULL significa “sconosciuto” e due valori sconosciuti non sono considerati uguali).
La PRIMARY KEY invece non permette NULL.

È una differenza sottile ma fondamentale.


Le relazioni: collegare le storie

Creiamo una seconda tabella:

CREATE TABLE ordini (
    id SERIAL PRIMARY KEY,
    utente_id INTEGER REFERENCES utenti(id),
    prodotto VARCHAR(100)
);

utente_id è una chiave esterna (FOREIGN KEY).

Significa:
“Questo valore deve esistere come id nella tabella utenti.”

Ora il database impedisce ordini “orfani”.

Le relazioni garantiscono coerenza tra tabelle diverse.


JOIN: quando le storie si incontrano

SELECT utenti.nome, ordini.prodotto
FROM utenti
JOIN ordini ON utenti.id = ordini.utente_id;

Il JOIN collega record di tabelle diverse sulla base delle chiavi.

Questo è il cuore del modello relazionale:
insiemi collegati da regole precise.


Integrità referenziale: protezione avanzata

Possiamo anche dire cosa succede se un utente viene cancellato:

FOREIGN KEY (utente_id) 
REFERENCES utenti(id)
ON DELETE CASCADE

Significa: se un utente viene eliminato, anche i suoi ordini vengono eliminati automaticamente.

Questa si chiama integrità referenziale.

Il database non si limita a memorizzare dati.
Difende le relazioni tra i dati.


Indici: quando i dati crescono

Con milioni di record, cercare diventa costoso.

Un indice è una struttura interna (spesso un B-tree) che permette ricerche rapide.

CREATE INDEX idx_email ON utenti(email);

Senza indice → scansione completa.
Con indice → accesso diretto.

Ma ogni indice:

  • occupa spazio
  • rallenta INSERT e UPDATE

Ogni ottimizzazione ha un prezzo.


Transazioni e proprietà ACID

Immagina un pagamento online.

BEGIN;

UPDATE conti SET saldo = saldo - 100 WHERE id = 1;
UPDATE conti SET saldo = saldo + 100 WHERE id = 2;

COMMIT;

Se qualcosa fallisce prima del COMMIT, si fa ROLLBACK.

Le transazioni rispettano le proprietà ACID:

  • Atomicità → tutto o niente
  • Consistenza → rispetto dei vincoli
  • Isolamento → operazioni concorrenti non si interferiscono
  • Durabilità → una volta confermato, il dato resta

Questo è il motivo per cui le banche usano database relazionali.


Aggregazioni e analisi

SQL non serve solo a salvare dati.

SELECT utente_id, COUNT(*)
FROM ordini
GROUP BY utente_id;

“Quanti ordini ha fatto ogni utente?”

Possiamo anche calcolare medie, somme, classifiche.

Con le window functions possiamo fare analisi più sofisticate mantenendo il dettaglio delle righe.


Normalizzazione: progettare prima di scrivere

Se salviamo lo stesso dato in 10 posti diversi, prima o poi diverge.

La normalizzazione aiuta a:

  • eliminare ridondanze inutili
  • prevenire anomalie
  • mantenere coerenza logica

Non è teoria accademica. È igiene progettuale.


Sicurezza e controllo

Un database reale permette di:

  • creare utenti con permessi diversi
  • limitare chi può leggere o scrivere
  • registrare operazioni

Non è solo archiviazione. È infrastruttura critica.


Perché SQL è ancora centrale

SQL esiste dagli anni ’70.
Eppure è ancora ovunque.

Perché unisce:

  • rigore matematico (algebra relazionale)
  • praticità ingegneristica
  • controllo della coerenza
  • ottimizzazione automatica

Il modello relazionale separa chiaramente:

  • identità (PRIMARY KEY)
  • validazione (UNIQUE, NOT NULL)
  • relazione (FOREIGN KEY)
  • accesso (SELECT)

È un sistema elegante perché ogni concetto ha un ruolo preciso.


Conclusione

Un database relazionale non è solo un contenitore di dati.
È un sistema di regole che protegge la verità della storia.

Le tabelle danno struttura.
Le chiavi danno identità.
I vincoli difendono la coerenza.
Le relazioni collegano le informazioni.
Le transazioni proteggono le operazioni critiche.

Imparare SQL significa imparare a costruire sistemi affidabili.
E costruire sistemi affidabili significa saper organizzare il caos in modo rigoroso.

È una competenza tecnica, certo.
Ma è anche una forma di disciplina mentale: trasformare informazioni sparse in una narrazione coerente e verificabile nel tempo.

aggiungi il create delete, drop, alter…

Perfetto. Completiamo la storia aggiungendo i comandi che permettono non solo di usare le tabelle… ma di crearle, modificarle e distruggerle. Perché un database non è immobile: evolve.

Integro questa parte nell’articolo come se fosse un nuovo capitolo naturale.


Creare la struttura: CREATE

Prima di inserire dati, dobbiamo creare la tabella.

CREATE TABLE utenti (
    id SERIAL PRIMARY KEY,
    nome VARCHAR(100) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL
);

Qui stiamo definendo:

  • le colonne (campi)
  • i tipi di dato
  • i vincoli (PRIMARY KEY, UNIQUE, NOT NULL)

CREATE serve a costruire la struttura.
È il momento in cui progettiamo la forma della storia.

Possiamo anche creare un indice:

CREATE INDEX idx_email ON utenti(email);

Oppure creare un database intero:

CREATE DATABASE negozio;

CREATE è il comando della nascita.


Modificare la struttura: ALTER

Nel mondo reale, i requisiti cambiano.

Serve aggiungere una colonna?
Cambiare un vincolo?

Si usa ALTER.

Aggiungere una colonna:

ALTER TABLE utenti
ADD COLUMN data_registrazione DATE;

Rendere obbligatorio un campo:

ALTER TABLE utenti
ALTER COLUMN nome SET NOT NULL;

Aggiungere un vincolo UNIQUE dopo la creazione:

ALTER TABLE utenti
ADD CONSTRAINT email_unica UNIQUE (email);

ALTER è il comando dell’evoluzione.

Permette di modificare la struttura senza distruggere tutto.


Cancellare dati: DELETE

DELETE rimuove righe (record), ma lascia intatta la struttura.

DELETE FROM utenti
WHERE id = 2;

Qui stiamo eliminando un utente specifico.

Senza WHERE:

DELETE FROM utenti;

Vengono eliminate tutte le righe, ma la tabella resta.

Struttura intatta. Dati spariti.

È una differenza fondamentale.


Eliminare la struttura: DROP

DROP è più radicale.

DROP TABLE utenti;

Qui non stiamo cancellando i record.
Stiamo cancellando la tabella intera.

Struttura + dati → eliminati.

Si può fare anche:

DROP DATABASE negozio;

Questo è l’equivalente informatico del “demoliamo l’edificio”.

DROP è irreversibile (a meno di backup).


Differenza tra DELETE e DROP

È una distinzione cruciale:

  • DELETE → elimina i dati (righe), mantiene la tabella.
  • DROP → elimina la tabella stessa.

Uno agisce sul contenuto.
L’altro sulla struttura.


Un altro comando utile: TRUNCATE

Vale la pena citarlo.

TRUNCATE TABLE utenti;

Elimina tutte le righe molto velocemente, ma mantiene la struttura.

È più veloce di DELETE senza WHERE, ma meno flessibile.


DDL vs DML: due categorie di comandi

Ora possiamo fare una distinzione più tecnica.

In SQL esistono due grandi famiglie:

DDL (Data Definition Language)
Definisce la struttura:

  • CREATE
  • ALTER
  • DROP

DML (Data Manipulation Language)
Manipola i dati:

  • SELECT
  • INSERT
  • UPDATE
  • DELETE

Questa separazione riflette una distinzione profonda:

  • La struttura definisce la forma della storia.
  • I dati riempiono quella forma.

Mettere tutto insieme

Ora la visione è completa.

Un database relazionale è composto da:

  • Tabelle (struttura)
  • Righe (record)
  • Colonne (campi)
  • Chiavi primarie (identità)
  • Vincoli UNIQUE e NOT NULL (coerenza)
  • Chiavi esterne (relazioni)
  • Indici (prestazioni)
  • Transazioni (affidabilità)

E SQL ci permette di:

  • creare (CREATE)
  • modificare (ALTER)
  • interrogare (SELECT)
  • inserire (INSERT)
  • aggiornare (UPDATE)
  • cancellare dati (DELETE)
  • eliminare strutture (DROP)

Non è solo un linguaggio.
È un sistema completo per costruire e mantenere mondi informativi coerenti.

E più si va avanti, più si capisce una cosa:
la vera potenza non è nei singoli comandi, ma nella disciplina che impongono. Struttura, regole, relazioni.

È questo che rende i database relazionali ancora oggi una delle invenzioni più solide e durature dell’informatica moderna.

scrivi il tutto assieme

L’importanza di una storia: SQL e DB relazionali

Quando lavoriamo con i dati, stiamo raccontando una storia.
Clienti che acquistano prodotti. Studenti che sostengono esami. Conti che trasferiscono denaro.

Un database relazionale esiste per mantenere questa storia ordinata, coerente e affidabile nel tempo.
SQL è il linguaggio che ci permette di costruirla, interrogarla, modificarla e proteggerla.

Partiamo dalle basi. Poi saliamo gradualmente verso concetti più avanzati.


Il problema: organizzare il caos

Senza struttura, i dati diventano contraddittori:

  • Due utenti con la stessa email
  • Un ordine senza cliente
  • Informazioni duplicate in più punti

Il caos nei dati non è spettacolare. È silenzioso. E si manifesta quando è troppo tardi.

Un database nasce per imporre regole.


Tabelle: la struttura della storia

Un database relazionale organizza i dati in tabelle.

Ogni tabella è composta da:

  • Colonne (campi) → descrivono che tipo di informazione stiamo salvando.
  • Righe (record) → rappresentano i singoli elementi.

Esempio:

idnomeemail
1Paolopaolo@email.it
2Lucialucia@email.it

Ogni riga è un record.
Ogni colonna è un campo.


Creare la struttura: CREATE

Prima di salvare dati, dobbiamo definire la struttura.

CREATE TABLE utenti (
    id SERIAL PRIMARY KEY,
    nome VARCHAR(100) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL
);

Qui stiamo definendo:

  • le colonne
  • il tipo di dato (VARCHAR, ecc.)
  • i vincoli

CREATE serve a costruire la forma della storia.

Possiamo anche creare un database:

CREATE DATABASE negozio;

Identità: PRIMARY KEY

La riga:

id SERIAL PRIMARY KEY

definisce la chiave primaria.

La PRIMARY KEY:

  • identifica ogni record in modo univoco
  • non può essere NULL
  • è il riferimento usato dalle altre tabelle

È la carta d’identità tecnica del record.
Ogni tabella può avere una sola PRIMARY KEY.

L’id è spesso un numero generato automaticamente. È stabile e non cambia.


Regole di coerenza: NOT NULL e UNIQUE

Un database serio non memorizza qualsiasi cosa. Impone regole.

NOT NULL

nome VARCHAR(100) NOT NULL

Significa: questo campo deve avere un valore.

In SQL, NULL non è una stringa vuota. È “assenza di valore”.
NOT NULL impedisce quella assenza.


UNIQUE

email VARCHAR(255) UNIQUE

Significa: nessuna email può comparire due volte.

Evita duplicati.


Differenza tra PRIMARY KEY e UNIQUE

A prima vista sembrano simili. Entrambi impediscono duplicati. Ma il loro ruolo è diverso.

PRIMARY KEY:

  • definisce l’identità ufficiale del record
  • è unica per tabella
  • non può essere NULL
  • viene usata nelle relazioni

UNIQUE:

  • è un vincolo di validazione
  • impedisce duplicazioni
  • può esistere su più colonne
  • può permettere NULL (dipende dal database, ma nello standard sì)

Esempio:

id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
codice_fiscale VARCHAR(16) UNIQUE

Qui:

  • id è l’identità tecnica
  • email e codice_fiscale sono campi che non devono duplicarsi

Concettualmente:

  • La PRIMARY KEY dice chi è il record.
  • UNIQUE dice questa informazione non può ripetersi.

Separare identità e regole è una scelta progettuale elegante.


Inserire, aggiornare, cancellare dati

Una volta creata la struttura, possiamo lavorare sui dati.

Inserire:

INSERT INTO utenti (nome, email)
VALUES ('Marco', 'marco@email.it');

Aggiornare:

UPDATE utenti
SET email = 'nuova@email.it'
WHERE id = 1;

Cancellare record:

DELETE FROM utenti
WHERE id = 2;

DELETE elimina le righe, ma lascia la tabella.


Eliminare la struttura: DROP

Se vogliamo eliminare completamente la tabella:

DROP TABLE utenti;

Qui spariscono sia struttura che dati.

Differenza fondamentale:

  • DELETE → elimina i dati
  • DROP → elimina la struttura

Uno agisce sul contenuto. L’altro sull’esistenza stessa della tabella.


Modificare la struttura: ALTER

I requisiti cambiano. Il database evolve.

Aggiungere una colonna:

ALTER TABLE utenti
ADD COLUMN data_registrazione DATE;

Aggiungere un vincolo:

ALTER TABLE utenti
ADD CONSTRAINT email_unica UNIQUE (email);

ALTER permette di modificare la struttura senza distruggerla.


Le relazioni: collegare le storie

Creiamo una seconda tabella:

CREATE TABLE ordini (
    id SERIAL PRIMARY KEY,
    utente_id INTEGER REFERENCES utenti(id),
    prodotto VARCHAR(100)
);

utente_id è una chiave esterna.

Significa: questo valore deve esistere come id nella tabella utenti.

Ora il database impedisce ordini senza utente.


JOIN: unire i dati

SELECT utenti.nome, ordini.prodotto
FROM utenti
JOIN ordini ON utenti.id = ordini.utente_id;

Il JOIN collega record di tabelle diverse.

È il momento in cui le storie si incontrano.


Indici: velocità su larga scala

Con milioni di record, cercare diventa costoso.

CREATE INDEX idx_email ON utenti(email);

Un indice permette ricerche più veloci.

Ma ogni indice:

  • occupa spazio
  • rallenta scritture

Ogni ottimizzazione ha un costo.


Transazioni: proteggere le operazioni

Immagina un trasferimento di denaro:

BEGIN;

UPDATE conti SET saldo = saldo - 100 WHERE id = 1;
UPDATE conti SET saldo = saldo + 100 WHERE id = 2;

COMMIT;

Se qualcosa fallisce prima del COMMIT, si può fare ROLLBACK.

Le transazioni rispettano le proprietà ACID:

  • Atomicità
  • Consistenza
  • Isolamento
  • Durabilità

Questo garantisce affidabilità.


Aggregazioni e analisi

SQL non serve solo a salvare dati. Serve a estrarre informazioni.

SELECT utente_id, COUNT(*)
FROM ordini
GROUP BY utente_id;

“Quanti ordini ha fatto ogni utente?”

Con funzioni più avanzate (come le window functions) possiamo fare classifiche, medie mobili, numerazioni per gruppo.


DDL e DML: due categorie

Possiamo distinguere:

DDL (Data Definition Language)
Definisce la struttura:

  • CREATE
  • ALTER
  • DROP

DML (Data Manipulation Language)
Manipola i dati:

  • SELECT
  • INSERT
  • UPDATE
  • DELETE

Struttura e contenuto sono due livelli distinti.
Ed è questa separazione che rende il sistema robusto.


Conclusione

Un database relazionale non è solo un archivio. È un sistema di regole.

Le tabelle danno forma.
Le chiavi danno identità.
I vincoli difendono la coerenza.
Le relazioni collegano le informazioni.
Gli indici migliorano le prestazioni.
Le transazioni proteggono le operazioni critiche.

SQL è lo strumento che governa tutto questo.

Impararlo significa imparare a organizzare il caos con metodo.
E quando si padroneggiano identità, regole e relazioni, si capisce che un database ben progettato non è solo tecnico. È una struttura logica che mantiene la verità dei dati nel tempo.

Lascia un commento