Se sei un programmatore, almeno una volta nella vita ti sarà capitato (o ti capiterà) di avere a che fare con un database e di conseguenza con le query SQL.
Potrebbe ad esempio capitare che il tuo codice venga consultato da altre persone, vuoi perchè lavori in team o perchè pubblichi i sorgenti su Github… Il problema è che non tutti riescono a scrivere correttamente, in modo ottimale, facilmente leggibile e con un’elevata velocità di elaborazione il codice SQL. In questo articolo vedremo alcune best practices utili per migliorare la leggibilità delle query SQL a vantaggio nostro e di tutti quelli che, per mille motivi, utilizzeranno il nostro codice. Se scrivi un codice “pulito” gli altri ti ringrazieranno.
Snake Case per schema, tabelle e colonne
Adotta uno stile unico di programmazione per il linguaggio SQL. Questo ti aiuterà moltissimo per mantenere il codice a lungo tempo. Esistono diversi stili di programmazione tra cui ricordiamo i più comuni:
- camelCase
- PascalCase
- kebab-case (difficilmente utilizzato nei linguaggi di programmazione)
- snake_case
Lo snake_case per il linguaggio SQL risulta essere, a mio parere, la soluzione ottimale per scrivere query.
Maiuscolo per le clausole
Quando formuli una query di selezione, inserimento o altro, dovresti sempre usare lettere maiuscole per le clausole SQL in quanto aiuterà te o chiunque legga il tuo codice a trovare facilmente quali operazioni/manipolazioni stai eseguendo. Anzichè scrivere cosi:
select id_ordine, numero from tb_ordini
puoi scrivere senz’altro cosi:
SELECT id_ordine, numero FROM tb_ordini
In questo modo a colpo d’occhio sapremo che si tratta di una query di selezione e quale tabella sta per essere interrogata.
Indentazione e/o la spaziatura
Avere una corretta indentazione del codice è molto importante perchè rende il codice pulito e quindi più facile da leggere per chiunque. Due regole da fissare in mente:
- Utilizza una riga per ogni colonna (nella SELECT)
- Scrivi un’istruzione per riga
Anzichè così:
SELECT colonnaB, FOO(colonna_c) FROM tabella_sinistra JOIN tabella_destra ON tabella_sinistra.colonnaA = tabella_destra.colonna WHERE espressione_filtro GROUP BY colonnaB HAVING espressione_filtro ORDER BY colonnaB ASC/DESC LIMIT ROW_COUNT;
dovremmo scrivere così:
SELECT colonna_b, FOO(colonna_c) FROM tabella_sinistra JOIN tabella_destra ON tabella_sinistra.colonna_a = tabella_destra.colonna_a WHERE espressione_filtro GROUP BY colonna_b HAVING espressione_filtro ORDER BY colonna_b ASC/DESC LIMIT ROW_COUNT;
In questo esempio sono stati applicati anche altre best practices e volutamente “corretti” i nomi di alcune colonne, in modo tale che la relazione JOIN sia ancora più chiara: utilizzano infatti lo stesso nome (colonna_a).
Alias
Gli alias vengono utilizzati per assegnare alle colonne un nome intuitivo definito dall’utente. Gli alias in SQL vengono creati utilizzando ‘AS’, seguito dal nome definito dall’utente.
Anzichè questo:
SELECT order_id, SUM(price) FROM tab1 INNER JOIN tab2 ON tab1.prod_id = tab2.prod_id GROUP BY order_id
potremmo usare degli alias sia per le funzioni, che per “accorciare” i nomi delle tabelle nei join, in questo modo:
SELECT t1.order_id, SUM(t1.price) AS sum_price FROM tabella1 AS t1 INNER JOIN tabella2 AS t2 ON t1.prod_id = t2.prod_id GROUP BY t1.order_id
Nomi di tabelle intuitivi
There are only two hard things in Computer Science: cache invalidation and naming things. — Phil Karlton
Ebbene si, alcuni programmatori peccano di poca fantasia. Durante la fase di progettazione è importante scegliere dei nomi intuitivi alle tabelle e ai campi. Tali nomi dovrebbero rappresentare ciò che stai cercando di ottenere. Quando si lavora in team vale sempre la pena ritagliare del tempo per definire delle convenzioni comuni. Ma sopratutto, quando si sceglie un nome a una tabella o un campo, non usare mai un nome “temporaneo” che verrà cambiato in seguito, perchè probabilmente non lo cambierai più…
Una query poco intuitiva potrebbe essere la seguente:
CREATE TABLE table1 AS SELECT data_ordine, COUNT(id_ordine) FROM ordini WHERE id_utente = 3 GROUP BY data_ordine
Questa query, non fa altro che creare una nuova tabella chiamata table1 che prenda i dati direttamente da una SELECT filtrata. La query sopra potrebbe essere ottimizzata in questo modo:
CREATE TABLE ordini_filtrati AS SELECT data_ordine, COUNT(id_ordine) AS totale_ordini FROM ordini WHERE id_utente = 3 GROUP BY data_ordine
Aggiungendo degli alias al posto giusto e una corretta nominazione della nuova tabella, la query risulta essere più comprensibile.
Commentare il codice
Commentare il codice è uno dei passaggi più importanti per rendere il codice leggibile e comprensibile. I commenti devono stare racchiusi tra /* */ e potrebbero seguire il seguente schema per descrivere gli aspetti dello sviluppo, senzaperò dilungarsi troppo in chiacchiere (il nostro obiettivo è scrivere codice, non un tema d’italiano):
- L’obiettivo del codice
- Nome dell’autore
- Data
- Descrizione del codice
/* Obiettivo: ottenere l'importo dell'ordine corrispondente a ciascun ordine Autore: Mario Rossi Data: 05 maggio 2022 Descrizione: questo codice fornisce l'id ordine e l'importo dell'ordine corrispondente unendo la tabella dettaglio_ordini e prodotti su id_prodotto (chiave primaria) */ SELECT prodotti.id_ordine, SUM(dettaglio_ordine.prezzo) AS importo_ordine FROM table1 AS dettaglio_ordine INNER JOIN table2 AS prodotti ON dettaglio_ordine.id_prodotto = prodotti.id_prodotto GROUP BY prodotti.id_ordine
Non abusare del carattere *
L’uso di SELECT * rende l’output un po’ una scatola nera in quanto nasconde le informazioni/colonne selezionate. L’uso dei nomi di colonna nella clausola SELECT è molto utile per capire quali colonne (o informazioni) stiamo selezionando per il nostro output. In molti casi l’utilizzo del carattere jolly * potrebbe rivelarsi controproducente, si pensi ad esempio a quelle tabelle strutturati con decine di campi, molti dei quali sono informazioni che non ci interessano ai fini della nostra SELECT oppure che contengono informazioni riservate.
Anzichè questo:
SELECT * FROM ordini
Utilizziamo questo in modo da definire al meglio l’interrogazione nonchè ottimizzare l’output:
SELECT id_ordine, data_ordine, importo_totale FROM ordini
SQL è fantastico e la sua flessibilità è un punto di forza ma può anche essere una trappola. Potresti non rendertene conto all’inizio, soprattutto se sei l’unico sviluppatore del progetto ma se a un certo punto, avessi la necessità di lavorare con un team o se qualcuno dovesse continuare il tuo lavoro, un codice SQL non ottimizzato senza una serie di best practice diventerà un peso.