Spiegazione delle visualizzazioni SQL: crea, utilizza ed evita le insidie, con esempi

  1. Home
  2. Blog
  3. Database e SQL

Database e SQL

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.

8 min di lettura
Spiegazione delle visualizzazioni SQL: creare, utilizzare ed evitare le trappole, con esempi

Punti chiave

  • 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 come customer_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

Lavora con Stack Quora

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.

Continua a leggere

Altre guide su test, intelligenza artificiale e sviluppo moderno

Ti è piaciuto questo articolo? Scegli un argomento e passa direttamente ai nostri tutorial più recenti.

Intelligenza artificiale

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 →
DevOps

Spiegazione 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 software

Spiegazione 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 test

Derisione 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 software

Spiegazione 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 SQL

DELETE 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 SQL

Spiegazione 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 software

Interfaccia 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 software

Spiegazione 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 software

Funzioni 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 artificiale

Cosa 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 →
DevOps

Monitoraggio 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 →
DevOps

Volumi 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 test

TDD 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 software

Git 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 software

List 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 SQL

SQL 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 →