BACK TO THE SERIESSviluppo web da zero · ゼロからのウェブ開発

Query SQL di base

18 - Query SQL di base


Le tabelle ci sono, le chiavi pure. Ora serve la lingua per parlare col database: si chiama SQL (Structured Query Language), ha cinquant'anni portati benissimo, ed è probabilmente la competenza con il miglior rapporto sforzo/durata di tutta l'informatica: quello che impari oggi valeva nel 1980 e varrà nel 2050.


E c'è una cosa che ti farà sorridere: SQL è un linguaggio dichiarativo. Dici cosa vuoi, non come ottenerlo: al piano di esecuzione pensa il database. Ti ricorda qualcosa? È la stessa filosofia dei framework frontend del capitolo 9. Te l'avevo detto che le buone idee girano.


🔍 SELECT: leggere


Il comando che scriverai più di tutti nella vita:

SQL · コード
1-- tutto il registro
2SELECT * FROM guardiani;
3
4-- solo alcune colonne
5SELECT nome, ruolo FROM guardiani;

L'asterisco è "tutte le colonne". Ma il potere vero arriva con i filtri:

SQL · コード
1-- solo le reclute
2SELECT * FROM guardiani WHERE ruolo = 'recluta';
3
4-- le reclute del castello 1, in ordine alfabetico, massimo 10
5SELECT * FROM guardiani
6WHERE ruolo = 'recluta' AND castello_id = 1
7ORDER BY nome
8LIMIT 10;

WHERE filtra le righe, ORDER BY le ordina, LIMIT ne prende un numero massimo. Si legge come una frase: "dammi i guardiani dove il ruolo è recluta, ordinati per nome, al massimo dieci". Dichiarativo, appunto.


✍️ INSERT, UPDATE, DELETE: scrivere


Gli altri tre si presentano da soli, anche perché li conosci già sotto mentite spoglie:

SQL · コード
1-- Create: arruolamento
2INSERT INTO guardiani (nome, ruolo, castello_id)
3VALUES ('Grenn', 'recluta', 1);
4
5-- Update: promozione
6UPDATE guardiani SET ruolo = 'ranger' WHERE id = 3;
7
8-- Delete: congedo
9DELETE FROM guardiani WHERE id = 3;

Esatto: è il CRUD del capitolo 12, nella sua lingua madre. INSERT è Create, SELECT è Read, UPDATE e DELETE si chiamano proprio così. I verbi HTTP erano la mappatura per il web; SQL è la mappatura per i dati.

Ora guarda di nuovo UPDATE e DELETE, e nota il WHERE. Adesso immaginali senza: DELETE FROM guardiani cancella tutte le righe. Nessuna conferma, nessun cestino. Ogni sviluppatore ha una storia dell'orrore che inizia con un WHERE dimenticato: scrivilo prima del resto della query, e sui database veri, prova prima con una SELECT.

🤝 JOIN: interrogare le relazioni


Le chiavi esterne del capitolo scorso servivano a questo momento. "Dammi i guardiani con il nome del loro castello" richiede dati da due tabelle, e il ponte si chiama JOIN:

SQL · コード
SELECT guardiani.nome, guardiani.ruolo, castelli.nome AS castello
FROM guardiani
JOIN castelli ON guardiani.castello_id = castelli.id;

Leggilo con calma: prendi i guardiani, agganciali ai castelli dove la chiave esterna incontra la chiave primaria, e dammi le colonne di entrambi (AS rinomina, per non confondere i due nome). Risultato:

TEXT · コード
1┌────────────────┬─────────────────┬───────────────────┐
2│ nome           │ ruolo           │ castello          │
3├────────────────┼─────────────────┼───────────────────┤
4│ Jon Snow       │ lord comandante │ Castello Nero     │
5│ Samwell Tarly  │ attendente      │ Castello Nero     │
6│ Eddison Tollet │ recluta         │ Forte Orientale   │
7└────────────────┴─────────────────┴───────────────────┘

I JOIN hanno varianti e profondità che scoprirai col tempo; per ora ti basta questo, che copre una quantità sorprendente di casi reali.


💉 La promessa mantenuta: ecco la SQL injection


Nel capitolo sulla sicurezza ti ho promesso che avresti visto coi tuoi occhi perché "mai fidarsi del client" è questione di vita o di morte. Il momento è arrivato.


Immagina un login che costruisce la query incollando l'input dell'utente nella stringa:

JAVASCRIPT · コード
// ⚠️ NON FARLO MAI: è l'esempio di come NON si fa
const query = "SELECT * FROM utenti WHERE nome = '" + input + "'";

Con un input normale (Jon), tutto bene. Ma un malintenzionato non scrive un nome. Scrive questo:

TEXT · コード
' OR '1'='1

Incollalo mentalmente nella stringa e guarda cosa diventa la query:

SQL · コード
SELECT * FROM utenti WHERE nome = '' OR '1'='1'

'1'='1' è sempre vero: la query restituisce tutti gli utenti. Con varianti dello stesso trucco si scavalcano login, si leggono dati altrui, si cancellano tabelle intere. Questa è la SQL injection: da vent'anni stabilmente sul podio delle vulnerabilità più sfruttate al mondo. Non perché sia sofisticata, ma perché è facile da commettere.

La difesa esiste, è semplice e la vedrai nel prossimo capitolo: mai costruire query concatenando input dell'utente. I dati viaggiano separati dal comando, con le query parametrizzate. Tienilo a mente ancora per qualche pagina.

✅ Conclusione


Ora parli la lingua dei dati: SELECT con filtri, ordinamenti e limiti, INSERT, UPDATE e DELETE (con rispetto per il WHERE), e il JOIN che trasforma le relazioni in risposte. E sai riconoscere l'attacco più famoso del web, che è già metà della difesa.


Resta l'ultimo miglio: far parlare il nostro server Fastify con un database vero. Nel prossimo capitolo chiudiamo il cerchio aperto sei capitoli fa: Samwell sta per smettere di sparire.