Spiegazione delle visualizzazioni SQL: Creare, utilizzare ed evitare le insidie con esempi
Una vista è una query salvata che puoi utilizzare come una tabella. Scopri come crearne uno, perché le visualizzazioni mantengono coerenti i report, cosa fanno e cosa non fanno per le prestazioni e le trappole che le rompono.
- Una vista è una query memorizzata con nome da cui è possibile selezionare come una tabella.
- Una visualizzazione normale non memorizza dati, quindi mostra sempre i risultati correnti.
- Le visualizzazioni semplificano query complesse, mantengono coerente la logica aziendale e possono limitare l’accesso alle colonne.
- Non effettuano una query più velocemente da soli, sebbene le viste materializzate possano farlo.
La stessa query di report di venti righe è stata copiata in cinque dashboard e ogni copia si è leggermente spostata. Uno conta gli ordini annullati, mentre un altro no. Visualizzazioni SQL risolvono questo problema definendo quella logica una volta, nel database, con un nome chiaro.
Abbiamo eseguito tutti gli esempi riportati di seguito in SQLite 3.50 e i risultati mostrati provengono da quell’esecuzione. Le viste sono SQL standard, ma dettagli come l’aggiornamento tramite una vista, le viste materializzate e la gestione delle dipendenze variano tra i database e li segnaliamo.
Cos’è una vista?
Una vista è un’istruzione SELECT salvata nel database con un nome. Quando esegui una query sulla vista, il database esegue la query salvata. Funziona come una tabella per la lettura, ma una vista normale non conserva la propria copia dei dati.
Pensa a un filtro salvato in un foglio di calcolo. Il filtro non è una seconda copia del foglio. È un modo di guardare gli stessi dati, che riflette sempre i valori più recenti.
Le tabelle campione
CREATE TABLE customers (
id INT PRIMARY KEY, name TEXT, city TEXT, email TEXT, credit_limit INT
);
CREATE TABLE orders (
id INT PRIMARY KEY, customer_id INT, total INT, status TEXT
);
INSERT INTO customers VALUES
(1,'Asha','Pune','asha@example.com',50000),
(2,'Ben','Delhi','ben@example.com',20000),
(3,'Chitra','Pune','chitra@example.com',80000);
INSERT INTO orders VALUES
(101,1,1200,'paid'), (102,1,800,'paid'),
(103,2,300,'pending'), (104,3,2500,'paid');
Crea una vista
Questa visualizzazione riepiloga gli ordini di ciascun cliente. Nasconde un join, un raggruppamento e un’espressione CASE dietro un nome semplice:
CREATE VIEW customer_sales AS
SELECT c.id, c.name, c.city,
COUNT(o.id) AS orders,
COALESCE(SUM(CASE WHEN o.status = 'paid' THEN o.total END), 0) AS paid_total
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
GROUP BY c.id, c.name, c.city;
Ora chiunque può usarlo, senza sapere come funziona:
SELECT * FROM customer_sales ORDER BY paid_total DESC;
-- 3 | Chitra | Pune | 1 | 2500
-- 1 | Asha | Pune | 2 | 2000
-- 2 | Ben | Delhi | 1 | 0
SELECT name, paid_total FROM customer_sales WHERE city = 'Pune';
-- Asha | 2000
-- Chitra | 2500
Ben appare con zero, perché la vista utilizza LEFT JOIN e COALESCE. Decisioni come questa, prese una volta nella vista, sono esattamente ciò che mantiene coerenti i report. Per rinfrescare la tua comprensione della gestione dei NULL, consulta Valori NULL SQL.
Le visualizzazioni sono sempre attuali
Poiché una visualizzazione normale esegue la query ogni volta, i nuovi dati vengono visualizzati immediatamente. Abbiamo aggiunto un ordine pagato per Ben e abbiamo nuovamente interrogato la vista:
INSERT INTO orders VALUES (105, 2, 900, 'paid');
SELECT name, paid_total FROM customer_sales WHERE name = 'Ben';
-- Ben | 900
Non è stato effettuato alcun passaggio di aggiornamento né copia da mantenere sincronizzata. Questa è la differenza fondamentale rispetto al salvataggio dei risultati della query in una tabella separata.
Nascondere le colonne
Le visualizzazioni vengono spesso utilizzate per esporre solo le colonne necessarie a una persona o a un’applicazione. Qui gli indirizzi e-mail e i limiti di credito vengono omessi:
CREATE VIEW public_customers AS
SELECT id, name, city FROM customers;
-- columns: id, name, city
Nei database con autorizzazioni, come PostgreSQL, SQL Server e MySQL, è possibile concedere a un utente del reporting l’accesso alla vista ma non alla tabella sottostante. SQLite non ha account utente, quindi potremmo mostrare solo la restrizione della colonna stessa. Tratta una vista come un livello di protezione. I dati sensibili necessitano ancora di un adeguato controllo degli accessi e alcuni database offrono sicurezza a livello di riga per filtrare le righe in base all’utente.
Prestazioni: le visualizzazioni non aumentano la velocità
Un mito comune è che le visualizzazioni rendano le query più veloci. Una vista normale viene sostituita dalla sua definizione quando la interroghi, quindi il database fa lo stesso lavoro come se avessi scritto tu stesso la query completa. Il nostro piano di esecuzione mostrava l’esecuzione dell’unione e del raggruppamento della vista come parte della query:
EXPLAIN QUERY PLAN SELECT * FROM customer_sales WHERE city = 'Pune';
-- CO-ROUTINE customer_sales
-- SCAN c ...
-- SEARCH o USING AUTOMATIC COVERING INDEX (customer_id=?) LEFT-JOIN
-- USE TEMP B-TREE FOR GROUP BY
-- SCAN customer_sales
Quindi una visualizzazione su una query lenta è ancora una query lenta. La velocità deriva dagli indici e da una buona progettazione delle query, come illustrato in Ottimizzazione delle query SQL e Spiegazione degli indici SQL. Fai attenzione anche alle visualizzazioni basate su altre visualizzazioni. Gli strati di annidamento facilitano l’unione più volte dello stesso grande tavolo senza accorgersene.
Viste materializzate
Una visione materializzatalo famemorizza i suoi risultati, come una tabella memorizzata nella cache. Le letture sono veloci, ma i dati sono aggiornati quanto l’ultimo aggiornamento.
-- PostgreSQL
CREATE MATERIALIZED VIEW daily_sales AS
SELECT order_date, SUM(total) AS revenue FROM orders GROUP BY order_date;
REFRESH MATERIALIZED VIEW daily_sales;
| Caratteristica | Visualizzazione normale | Vista materializzata |
|---|---|---|
| Memorizza i dati | No | Sì |
| Freschezza | Sempre attuale | A partire dall’ultimo aggiornamento |
| Leggi la velocità | Uguale alla query | Veloce |
| Costo di archiviazione | Nessuno | Sì |
| Buono per | Semplificazione, coerenza | Report e dashboard pesanti |
Il supporto varia. PostgreSQL e Oracle hanno viste materializzate e SQL Server offre viste indicizzate con le proprie regole. SQLite e MySQL ne sono sprovvisti, quindi le persone utilizzano una tabella di riepilogo regolare aggiornata in base a una pianificazione. Non abbiamo eseguito l’esempio PostgreSQL per questo articolo.
Suggerimento: prima di creare una vista materializzata, decidi quanto possono essere obsoleti i dati. “Aggiornato ogni ora” deve essere accettabile per le persone che leggono il rapporto, quindi diglielo.
Puoi aggiornare una vista?
Dipende dal database e dalla vista. Una vista semplice su una singola tabella, senza raggruppamento o DISTINCT, può spesso essere aggiornata in PostgreSQL, MySQL e SQL Server e la modifica passa alla tabella. Una vista con join o aggregati generalmente non può, perché il database non è in grado di indicare quale riga modificare.
SQLite non consente affatto la scrittura diretta sulle visualizzazioni. Il nostro tentativo è fallito:
INSERT INTO customer_sales (name) VALUES ('X');
-- cannot modify customer_sales because it is a view
Alcuni database supportano INSTEAD OF trigger per rendere scrivibile una vista e molti offrono WITH CHECK OPTION, che interrompe le scritture che non sarebbero visibili attraverso la vista. In pratica, la maggior parte dei team mantiene le visualizzazioni di sola lettura e scrive nelle tabelle.
Dipendenze e rotture
Una vista dipende dalle tabelle da cui legge. Abbiamo creato una vista su una tabella, quindi abbiamo rilasciato la tabella:
CREATE TABLE ghost AS SELECT 1 AS x;
CREATE VIEW v_ghost AS SELECT x FROM ghost;
DROP TABLE ghost;
SELECT * FROM v_ghost;
-- no such table: main.ghost
SQLite ha consentito l’eliminazione e ha fallito solo in seguito, quando è stata utilizzata la vista. Altri database, come PostgreSQL, si rifiutano di eliminare una tabella da cui dipende una vista, a meno che non si aggiunga CASCADE, che rimuove anche la vista. In ogni caso, rinominare o eliminare una colonna può interrompere le visualizzazioni, quindi controllale nei tuoi test di regressione dopo le modifiche allo schema.
C’è anche una sottile trappola con SELECT * in una vista. Abbiamo creato CREATE VIEW star AS SELECT * FROM customers, quindi abbiamo aggiunto una colonna alla tabella. In SQLite, la vista ha rilevato la nuova colonna. Altri database, incluso PostgreSQL, espandono l’elenco delle colonne quando viene creata la vista, quindi le nuove colonne non vengono visualizzate. Quindi elenca le colonne in modo esplicito. Documenta la vista e si comporta allo stesso modo ovunque.
Gestione delle visualizzazioni
| Compito | Sintassi comune |
|---|---|
| Crea | CREA VISTA nome COME SELEZIONA ... |
| Sostituisci | CREATE OR REPLACE VIEW (PostgreSQL, MySQL, Oracle) |
| Sostituisci in SQL Server | CREA O MODIFICA VISTA |
| Rimuovi | Nome della VISUALIZZAZIONE DROP |
| Rimuovi in sicurezza | DROP VIEW SE ESISTE nome |
L’eliminazione di una visualizzazione rimuove solo la query salvata. Nel nostro test, la tabella customers aveva ancora tutte e tre le righe dopo aver eliminato public_customers. Mantieni le definizioni delle viste nel controllo della versione insieme alle migrazioni, in modo che le modifiche vengano esaminate come qualsiasi altro codice.
Vista vs CTE vs tabella
| Opzione | A vita | Memorizza i dati | Meglio per |
|---|---|---|---|
| Visualizza | Fino alla caduta | No | Logica condivisa utilizzata da molte query |
| CTE | Una dichiarazione | No | Organizzazione di una singola query complessa |
| Vista materializzata | Fino alla caduta | Sì | Letture veloci di risultati costosi |
| Tabella | Fino alla caduta | Sì | I dati reali |
Errori comuni
- Mi aspettavo un aumento di velocità. Una visualizzazione normale esegue la query ogni volta.
- Utilizzo di
SELECT *nelle visualizzazioni. Il comportamento differisce tra i database quando le tabelle cambiano. - Nidificazione profonda. Le visualizzazioni basate su visualizzazioni nascondono unioni costose.
- Utilizzo di ORDER BY all’interno di una vista. L’ordine non è garantito quando lo esegui una query, quindi ordina la query esterna.
- Nomi poco chiari. Un prefisso come
v_, o un nome chiaro comecustomer_sales, aiuta. - Dimenticare le visualizzazioni durante le migrazioni. Testarle dopo ogni modifica dello schema.
Considerazioni finali
Le visualizzazioni rappresentano un modo semplice per assegnare una posizione logica importante nel database. Usali per mantenere i report coerenti e per nascondere le colonne non necessarie, non come un trucco per le prestazioni. Per iniziare, trova una query che appare in diversi punti del tuo codice, trasformala in una vista con colonne esplicite e indirizza ad essa ciascun chiamante.
Domande frequenti
Cos’è una vista in SQL?
Una vista è una query SELECT salvata con un nome. Lo interroghi come una tabella e il database esegue ogni volta la query sottostante, quindi i risultati sono sempre aggiornati.
Una vista SQL memorizza i dati?
Una visualizzazione normale non memorizza i dati, ma solo la query. Una vista materializzata memorizza i risultati e deve essere aggiornata per rimanere aggiornata.
Le visualizzazioni sono più veloci delle tabelle?
No. Una visualizzazione normale svolge lo stesso lavoro della query sottostante. Le visualizzazioni materializzate possono accelerare le letture, a scapito dell’archiviazione e della freschezza.
Puoi inserire in una vista?
A volte. Le semplici visualizzazioni a tabella singola sono spesso aggiornabili in PostgreSQL, MySQL e SQL Server. Le visualizzazioni con join o raggruppamenti di solito non lo sono e SQLite non lo consente.
Cosa succede a una vista se la tabella viene eliminata?
Dipende dal database. Alcuni si rifiutano di eliminare la tabella mentre una vista dipende da essa, mentre altri lo consentono e la vista fallisce quando viene interrogata.
Continua a imparare
Hai bisogno di aiuto con test, WordPress o SEO?
Aiutiamo i team a fornire software migliore e a far crescere i loro siti. Raccontaci a cosa stai lavorando e ti suggeriremo chiaramente il prossimo passo.
Altre guide su test, intelligenza artificiale e sviluppo moderno
Ti è piaciuto questo articolo? Scegli un argomento e passa direttamente ai nostri tutorial più recenti.
Spiegazione delle allucinazioni dell'intelligenza artificiale: perché i modelli linguistici inventano le cose e come ridurle
Spiegazione delle allucinazioni dell'intelligenza artificiale: cosa sono, perché i modelli linguistici le producono, tipi comuni, come ridurle con b…
Leggi l'articolo →DevOpsSpiegazione delle variabili d'ambiente: file .env, segreti e configurazione eseguiti correttamente
Variabili d'ambiente spiegate con esempi Python che abbiamo eseguito: lettura e impostazione, perché ogni valore è una stringa, file .env, ereditari…
Leggi l'articolo →Sviluppo softwareSpiegazione della limitazione della velocità API: algoritmi, intestazioni e gestione degli errori 429
La limitazione della velocità dell'API spiegata con una simulazione che abbiamo eseguito: bucket di token, finestra fissa, finestra scorrevole, risp…
Leggi l'articolo →Automazione dei testDerisione in Python: unittest.mock, patch e gli errori che fanno mentire i test
Mocking in Python con unittest.mock, testato: Mock e return_value, side_effect, patch dove viene utilizzato un nome, specifiche e autospec, date moc…
Leggi l'articolo →Test del softwareSpiegazione della copertura del codice: copertura di linea o di filiale e cosa significa realmente il 100%.
Copertura del codice spiegata con una vera esecuzione di cover.py: copertura di linea, ramo e condizione, lettura di un rapporto, perché la copertur…
Leggi l'articolo →Database e SQLDELETE vs TRUNCATE vs DROP in SQL: differenze, rollback e quando utilizzarli
DELETE vs TRUNCATE vs DROP spiegato con SQL testato: cosa rimuove, rollback, trigger, reimpostazione dell'identità, velocità e come differiscono Pos…
Leggi l'articolo →Database e SQLSpiegazione delle visualizzazioni SQL: crea, utilizza ed evita le insidie, con esempi
Viste SQL spiegate con le query che abbiamo eseguito: creazione di una vista, risultati in tempo reale, nascondere colonne, prestazioni, viste aggio…
Leggi l'articolo →Sviluppo softwareInterfaccia TypeScript e tipo: differenze reali, testate con il compilatore
Interfaccia TypeScript vs tipo, verificata con il vero compilatore: cosa possono fare entrambi, cosa può fare solo uno, fusione delle dichiarazioni,…
Leggi l'articolo →Sviluppo softwareSpiegazione di Python *args e **kwargs: funzioni flessibili con esempi chiari
Python *args e **kwargs spiegati con il codice che abbiamo eseguito: compressione e decompressione, ordine dei parametri, argomenti solo per parole …
Leggi l'articolo →Sviluppo softwareFunzioni Lambda Python: sintassi, usi reali e quando non usarli
Funzioni lambda Python spiegate con il codice che abbiamo eseguito: sintassi, ordinamento con chiave, mappa e filtro, chiusure, trap dell'associazio…
Leggi l'articolo →Intelligenza artificialeCosa sono gli agenti AI? Come funzionano, con un semplice ciclo di agenti che puoi eseguire
Cosa sono gli agenti IA? Una semplice guida al ciclo dell'agente, agli strumenti, alla memoria e ai guardrail, con un piccolo ciclo Python che abbia…
Leggi l'articolo →DevOpsMonitoraggio vs osservabilità: la vera differenza, con log, metriche e tracce
Spiegazione del monitoraggio e dell'osservabilità: errori noti e sconosciuti, log, metriche e tracce, una procedura dettagliata sugli incidenti di p…
Leggi l'articolo →DevOpsVolumi Docker e montaggi di associazione: mantenere i dati del contenitore nel modo giusto
Volumi Docker e montaggi di collegamento spiegati: perché i dati del contenitore scompaiono, volumi denominati, montaggi di collegamento, tmpfs, ese…
Leggi l'articolo →Automazione dei testTDD vs BDD: differenze chiave, una caratteristica costruita in entrambi i modi e quando utilizzarli ciascuno
TDD vs BDD spiegato con una funzione di sconto costruita in entrambi i modi: refactoring rosso-verde con il codice che abbiamo eseguito, scenari "Da…
Leggi l'articolo →Sviluppo softwareGit merge vs rebase: differenze, esempi e quando usare ciascuno
Git merge vs rebase spiegato con output reale del log, una tabella di confronto, la regola d'oro del rebase e un flusso di lavoro sicuro per i team.
Leggi l'articolo →Sviluppo softwareList comprehension in Python: sintassi, esempi e quando evitarla
List comprehension in Python spiegata: sintassi, filtri, if-else, cicli annidati, tempi misurati e i casi in cui un normale ciclo for è meglio.
Leggi l'articolo →Database e SQLSQL JOIN spiegati con esempi (Inner, Left, Right, Full)
Capisci i JOIN SQL passo dopo passo con tabelle e query di esempio: INNER, LEFT, RIGHT, FULL, CROSS e SELF, con errori comuni e consigli sulle prest…
Leggi l'articolo →