Una vista è una query salvata
Una vista è un'istruzione SELECT con un nome. Una volta creata, puoi interrogarla come una tabella, ma non viene memorizzato niente. Ogni volta che leggi da una vista, SQLite esegue da capo la query sottostante.
paid_orders ha l'aspetto e il comportamento di una tabella. Ha delle colonne, puoi farci SELECT, puoi usarla in un join. Ma sotto il cofano ogni query si espande nel filtro originale WHERE status = 'paid'.
Questo è tutto il modello mentale: una vista è un alias per una query.
Perché le viste sono utili
Il vantaggio principale è il nome. Una query complicata riceve un nome breve e descrittivo, e il resto del codice resta leggibile:
Senza la vista, chiunque la usi dovrebbe scriversi da solo il GROUP BY, e chiunque potrebbe sbagliare il filtro. Con la vista, l'aggregazione è definita una volta sola. Chi la usa chiede semplicemente customer_totals e aggiunge sopra i filtri che gli servono.
Le viste funzionano anche come confine in stile permessi. Se una query non deve esporre una colonna password_hash, crea una vista che seleziona tutto tranne quella colonna e fai usare la vista al codice dell'applicazione.
Sintassi di CREATE VIEW
La forma completa:
CREATE [TEMPORARY] VIEW [IF NOT EXISTS] view_name [(column_aliases)] AS
SELECT ...;
Alcune cose da sapere:
IF NOT EXISTSsalta in silenzio la creazione se la vista esiste già.TEMPORARY(oTEMP) crea una vista che sparisce quando la connessione si chiude.- Gli alias di colonna tra parentesi ti permettono di rinominare le colonne della vista senza toccare la
SELECTsottostante.
La vista espone nomi più comodi (item, dollars) senza rinominare le colonne della tabella di origine.
Sostituire ed eliminare le viste
SQLite non ha CREATE OR REPLACE VIEW né ALTER VIEW. Per cambiare la definizione di una vista, eliminala e ricreala:
DROP VIEW IF EXISTS active_orders; è la forma sicura: non dà errore se la vista non c'è. Eliminare una vista non tocca mai le tabelle sottostanti; stai cancellando solo la query salvata.
Viste temporanee
Una TEMP VIEW esiste solo per la connessione al database corrente. Quando la connessione si chiude, la vista sparisce. Utile per sessioni di analisi al volo in cui non vuoi lasciarti dietro definizioni:
Le viste temporanee ti permettono anche di usare un nome di query senza impegnarti a inserirlo nello schema: comodo durante l'esplorazione.
Le viste sono in sola lettura per impostazione predefinita
Questo è il tranello più importante. Non puoi fare INSERT, UPDATE o DELETE direttamente attraverso una vista:
sqlite> INSERT INTO paid_orders (customer, amount) VALUES ('Eve', 50);
Runtime error: cannot modify paid_orders because it is a view
La soluzione sono i trigger INSTEAD OF. Scrivi un trigger che si attiva al posto del tentativo di scrittura e lo traduce in un'operazione reale sulla tabella sottostante:
La vista resta una vista, ma ora le scritture su di essa hanno un posto dove andare. Vediamo i trigger per bene nella prossima pagina.
Niente viste materializzate: costruiscile da te
Alcuni database ti permettono di salvare su disco i risultati di una vista e aggiornarli su richiesta. SQLite no. Ogni lettura di una vista riesegue la query sottostante. Per la maggior parte dei carichi di lavoro va benissimo: SQLite è veloce e il pianificatore di query è bravo. Per le aggregazioni costose interrogate molte volte, crea una vera tabella e tienila sincronizzata tu:
Poi aggiorneresti la cache a intervalli regolari, oppure collegheresti dei trigger su orders per tenerla aggiornata. È lavoro manuale, ma è anche l'unica opzione in SQLite.
Elencare le viste
I metadati delle viste stanno in sqlite_master insieme a tabelle e indici:
La colonna sql ti restituisce l'istruzione CREATE VIEW originale: utile quando hai dimenticato cosa fa una vista. Nella CLI, .schema view_name stampa la stessa cosa in modo più pulito.
Quando usare una vista
Le viste valgono la pena quando:
- Una query non banale viene riutilizzata in tre o più punti. Darle un nome una volta è meglio che fare copia e incolla.
- Vuoi esporre a una parte dell'applicazione un sottoinsieme selezionato di colonne o righe.
- Un'aggregazione è concettualmente una cosa sola (
monthly_sales,active_users) che chi la usa dovrebbe trattare come un sostantivo.
Lascia perdere la vista quando:
- La query è usata in un solo punto. Scrivila direttamente lì.
- Le prestazioni contano e la query sottostante è costosa: paghi quel costo a ogni lettura. Salva invece i risultati in una vera tabella.
- La vista dipende da un'altra vista che dipende da un'altra vista ancora. SQLite gestisce bene l'annidamento, ma una catena di tre o quattro viste rende difficile seguire l'SQL reale durante il debug.
Prossimo passo: trigger
Viste e trigger compaiono spesso insieme: lo schema INSTEAD OF che rende scrivibili le viste è uno dei motivi principali per cui esistono i trigger. I trigger sono utili anche da soli per i log di audit, gli aggiornamenti a cascata e per imporre invarianti. È la prossima pagina.
Domande frequenti
Cos'è una vista in SQLite?
Una vista è un'istruzione SELECT salvata che puoi interrogare come una tabella. Non memorizza dati: ogni volta che la leggi, SQLite riesegue la query sottostante. Le viste sono utili per dare un nome una volta sola a una query complessa e riutilizzarla ovunque, o per nascondere colonne che chi la usa non deve vedere.
Si può fare INSERT o UPDATE attraverso una vista in SQLite?
Non direttamente. In SQLite le viste sono in sola lettura: INSERT, UPDATE e DELETE su una vista falliscono. Puoi rendere scrivibile una vista collegandole dei trigger INSTEAD OF che traducono la scrittura in operazioni sulle tabelle sottostanti.
SQLite supporta le viste materializzate?
No. SQLite ha solo viste normali (virtuali): la query viene eseguita ogni volta che leggi dalla vista. Se ti servono risultati in cache, crea una vera tabella e aggiornala tu, oppure usa un trigger per tenerla sincronizzata con le tabelle di origine.
Come si elencano tutte le viste di un database SQLite?
Interroga sqlite_master: SELECT name FROM sqlite_master WHERE type = 'view';. Nella CLI, .schema mostra le istruzioni CREATE VIEW e .tables elenca le viste insieme alle tabelle.