Menu

Vues SQLite : CREATE VIEW, vues temporaires et INSTEAD OF

Tout savoir sur les vues SQLite : sauvegarder une requête comme table virtuelle, utiliser les vues temporaires et contourner leur côté lecture seule.

Cette page contient des éditeurs exécutables — modifiez, exécutez et voyez la sortie instantanément.

Une vue, c'est une requête enregistrée

Une vue SQLite, c'est tout simplement une requête SELECT à laquelle on a donné un nom. Une fois créée, on peut l'interroger comme une table classique — sauf que rien n'est réellement stocké. À chaque lecture d'une vue, SQLite réexécute la requête sous-jacente.

paid_orders ressemble à une table et se comporte comme telle. Elle a des colonnes, on peut faire un SELECT dessus, on peut la joindre à d'autres tables. Mais en coulisses, chaque requête est développée pour réintégrer le filtre WHERE status = 'paid' d'origine.

Voilà tout le modèle mental à retenir : une vue, c'est un alias pour une requête.

À quoi servent les vues SQLite

Le principal intérêt, c'est de pouvoir nommer une requête. Une requête complexe se voit attribuer un nom court et parlant, et le reste de votre code reste lisible :

Sans vue, chaque appelant devrait écrire son propre GROUP BY — et n'importe lequel d'entre eux pourrait se tromper sur le filtre. Avec une vue, l'agrégation n'est définie qu'une seule fois. Les appelants demandent simplement customer_totals et ajoutent par-dessus les filtres supplémentaires dont ils ont besoin.

Les vues servent aussi de barrière, un peu comme un système de permissions. Si une requête ne doit pas exposer une colonne password_hash, créez une vue qui sélectionne toutes les colonnes sauf celle-là, puis faites en sorte que le code applicatif passe par cette vue.

Syntaxe de CREATE VIEW SQLite

La forme complète :

CREATE [TEMPORARY] VIEW [IF NOT EXISTS] view_name [(column_aliases)] AS
SELECT ...;

Quelques points utiles à garder en tête :

  • IF NOT EXISTS ignore silencieusement la création si la vue existe déjà.
  • TEMPORARY (ou TEMP) crée une vue temporaire qui disparaît à la fermeture de la connexion.
  • Les alias de colonnes entre parenthèses permettent de renommer les colonnes de la vue sans toucher au SELECT sous-jacent.

La vue affiche des noms plus parlants (item, dollars) sans qu'il soit nécessaire de renommer les colonnes dans la table source.

Remplacer et supprimer une vue SQLite

SQLite ne propose ni CREATE OR REPLACE VIEW ni ALTER VIEW. Pour modifier la définition d'une vue, il faut donc la supprimer puis la recréer :

DROP VIEW IF EXISTS active_orders; est la forme sûre — elle ne déclenche pas d'erreur si la vue n'existe pas. Supprimer une vue n'affecte jamais les tables sous-jacentes ; vous effacez uniquement la requête enregistrée.

Vue temporaire SQLite

Une TEMP VIEW n'existe que pour la connexion en cours à la base. Dès que la connexion se ferme, la vue disparaît. Pratique pour des sessions d'analyse ponctuelles, quand on ne veut pas laisser traîner de définitions :

Les vues temporaires permettent aussi de masquer le nom d'une requête sans l'inscrire durablement dans votre schéma — bien pratique en phase d'exploration.

Les vues SQLite sont en lecture seule par défaut

C'est le piège le plus important à connaître. Impossible de faire un INSERT, un UPDATE ou un DELETE directement à travers une vue :

sqlite> INSERT INTO paid_orders (customer, amount) VALUES ('Eve', 50);
Runtime error: cannot modify paid_orders because it is a view

La solution, ce sont les triggers INSTEAD OF. Concrètement, vous écrivez un trigger qui se déclenche à la place de la tentative d'écriture et qui la traduit en une vraie opération sur la table sous-jacente :

La vue reste une vue — mais les écritures qui la ciblent ont désormais une destination. On verra les triggers en détail sur la page suivante.

Pas de vue matérialisée dans SQLite — à vous de la simuler

Certains SGBD permettent de mettre en cache le résultat d'une vue sur disque et de le rafraîchir à la demande. SQLite, lui, ne le fait pas. Chaque lecture d'une vue ré-exécute la requête sous-jacente. Dans la plupart des cas, ça suffit largement — SQLite est rapide et son planificateur de requêtes fait du bon boulot. En revanche, pour des agrégations coûteuses interrogées très souvent, mieux vaut créer une vraie table et la maintenir synchronisée vous-même :

Vous pouvez ensuite rafraîchir ce cache via une tâche planifiée, ou poser des triggers sur orders pour le tenir à jour. C'est du boulot manuel, certes — mais sous SQLite, vous n'avez pas vraiment le choix.

Lister les vues SQLite

Les métadonnées des vues sont stockées dans sqlite_master, au même endroit que les tables et les index :

La colonne sql te renvoie l'instruction CREATE VIEW d'origine — pratique quand vous avez oublié ce que fait une vue. Dans le CLI, .schema nom_de_la_vue affiche la même chose en plus lisible.

Quand utiliser une vue SQLite

Les vues SQLite sont vraiment utiles dans ces cas :

  • Une requête un peu costaude est réutilisée à trois endroits ou plus. Lui donner un nom une bonne fois pour toutes vaut mieux que du copier-coller.
  • Vous voulez exposer un sous-ensemble bien choisi de colonnes ou de lignes à une partie de l'application.
  • Une agrégation représente conceptuellement une seule chose (monthly_sales, active_users) que le code appelant doit manipuler comme une entité à part entière.

Évitez la vue quand :

  • La requête ne sert qu'à un seul endroit. Mettez-la directement dans le code.
  • La performance compte et la requête sous-jacente coûte cher — vous payez ce coût à chaque lecture. Mieux vaut mettre les résultats en cache dans une vraie table.
  • La vue dépend d'une autre vue qui dépend d'une autre vue. SQLite gère très bien l'imbrication, mais une chaîne de trois ou quatre vues rend le SQL réel pénible à suivre au moment du debug.

La suite : les triggers

Vues et triggers vont souvent de pair — le pattern INSTEAD OF qui rend les vues modifiables est d'ailleurs l'une des raisons majeures pour lesquelles les triggers existent. Mais les triggers servent aussi à plein d'autres choses : journalisation d'audit, mises à jour en cascade, ou encore pour faire respecter des invariants. C'est le sujet de la page suivante.

Questions fréquentes

C'est quoi une vue dans SQLite ?

Une vue, c'est une requête SELECT enregistrée que vous pouvez interroger comme s'il s'agissait d'une table. Elle ne stocke rien : à chaque lecture, SQLite réexécute la requête sous-jacente. C'est pratique pour nommer une requête complexe une bonne fois pour toutes et la réutiliser partout, ou pour masquer des colonnes que l'appelant n'a pas besoin de voir.

Peut-on faire un INSERT ou un UPDATE à travers une vue SQLite ?

Pas directement. Les vues SQLite sont en lecture seule : un INSERT, un UPDATE ou un DELETE sur une vue échoue. Pour rendre une vue modifiable, il faut y attacher des déclencheurs INSTEAD OF qui traduisent l'écriture en opérations sur les tables sous-jacentes.

SQLite gère-t-il les vues matérialisées ?

Non. SQLite ne propose que des vues classiques (virtuelles) : la requête est rejouée à chaque lecture. Si vous avez besoin de résultats en cache, crée une vraie table et rafraîchis-la vous-même, ou utilise un déclencheur pour la garder synchronisée avec les tables sources.

Comment lister toutes les vues d'une base SQLite ?

Interroge sqlite_master : SELECT name FROM sqlite_master WHERE type = 'view';. En ligne de commande, .schema affiche les instructions CREATE VIEW, et .tables liste les vues à côté des tables.

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER