Skip to content

Les vues – classiques et matérialisées

Bonne lecture et bon apprentissage !
Junior TSAFACK – 20/08/2026
⏱️ Temps de lecture estimé : 9 minutes


Après avoir exploré les index qui améliorent les performances des requêtes, nous abordons maintenant un outil tout aussi puissant : les vues. Les vues permettent de simplifier l’accès aux données, de masquer la complexité des requêtes et de gérer finement les droits d’accès. PostgreSQL propose deux types de vues : les vues classiques (virtuelles) et les vues matérialisées (physiques). Ce cours vous présente ces deux concepts et vous aide à choisir la bonne solution selon vos besoins.


Une vue (ou view) est une requête SQL sauvegardée dans la base de données. Elle se comporte comme une table virtuelle : vous pouvez l’interroger avec SELECT, et même, dans certains cas, effectuer des mises à jour.

Bénéfice Description
Simplification Évitez de réécrire des requêtes complexes (jointures, agrégations) à chaque fois.
Abstraction Masquez la structure réelle des tables (normalisation, jointures multiples).
Sécurité Limitez l’accès à certaines colonnes ou lignes (masquage de données).
Réutilisabilité Une vue peut être utilisée dans d’autres vues ou requêtes.
Évolution Modifiez la vue sans changer les applications qui l’utilisent.

Une vue classique (aussi appelée vue virtuelle) est une requête stockée. Elle ne contient pas de données physiques : chaque fois que vous l’interrogez, PostgreSQL exécute la requête qui la définit.

CREATE VIEW nom_vue AS
SELECT colonnes
FROM tables
[WHERE condition]
[WITH CHECK OPTION];

Créons une table de produits et une vue qui simplifie l’accès aux produits en stock.

-- Table des produits
CREATE TABLE produits (
id SERIAL PRIMARY KEY,
nom VARCHAR(100) NOT NULL,
prix NUMERIC(10,2) NOT NULL,
stock INTEGER NOT NULL DEFAULT 0,
categorie VARCHAR(50)
);
-- Insertion de données
INSERT INTO produits (nom, prix, stock, categorie) VALUES
('Ordinateur portable', 899.99, 15, 'Informatique'),
('Souris sans fil', 29.99, 50, 'Informatique'),
('Clavier mécanique', 79.99, 30, 'Informatique'),
('Écran 27 pouces', 299.99, 8, 'Informatique'),
('Table de bureau', 149.99, 5, 'Mobilier'),
('Chaise ergonomique', 199.99, 12, 'Mobilier');
-- Créer une vue des produits en stock (stock > 0)
CREATE VIEW produits_disponibles AS
SELECT id, nom, prix, stock, categorie
FROM produits
WHERE stock > 0;
-- Interroger la vue
SELECT * FROM produits_disponibles;

Résultat (tous les produits sauf ceux à stock 0) :

id nom prix stock categorie
1 Ordinateur portable 899.99 15 Informatique
2 Souris sans fil 29.99 50 Informatique
3 Clavier mécanique 79.99 30 Informatique
4 Écran 27 pouces 299.99 8 Informatique
5 Table de bureau 149.99 5 Mobilier
6 Chaise ergonomique 199.99 12 Mobilier
  • Zéro stockage : aucune donnée dupliquée.
  • Toujours à jour : la vue reflète en temps réel l’état des tables.
  • Facile à créer et modifier.
  • Performance : chaque accès exécute la requête (coût potentiel élevé).
  • Pas d’index : impossible d’indexer directement une vue (mais on peut indexer les tables sous-jacentes).

Les vues brillent particulièrement lorsqu’elles encapsulent des jointures complexes.

-- Table des catégories
CREATE TABLE categories (
id SERIAL PRIMARY KEY,
nom VARCHAR(50) NOT NULL
);
INSERT INTO categories (nom) VALUES ('Informatique'), ('Mobilier'), ('Électroménager');
-- Ajout de la clé étrangère à produits
ALTER TABLE produits ADD COLUMN categorie_id INTEGER REFERENCES categories(id);
-- Mise à jour des données
UPDATE produits SET categorie_id = 1 WHERE categorie = 'Informatique';
UPDATE produits SET categorie_id = 2 WHERE categorie = 'Mobilier';
ALTER TABLE produits DROP COLUMN categorie;
-- Créer une vue qui joint produits et categories
CREATE VIEW produits_detail AS
SELECT
p.id,
p.nom AS produit,
p.prix,
p.stock,
c.nom AS categorie
FROM produits p
INNER JOIN categories c ON p.categorie_id = c.id;
-- Interroger la vue
SELECT * FROM produits_detail;

Résultat :

id produit prix stock categorie
1 Ordinateur portable 899.99 15 Informatique
2 Souris sans fil 29.99 50 Informatique

💡 Bon à savoir : Les vues peuvent utiliser des fonctions, des sous-requêtes, des UNION, et même des requêtes récursives (WITH RECURSIVE).


Mise à jour via une vue (règle de mise à jour)

Section titled “Mise à jour via une vue (règle de mise à jour)”

Les vues classiques sont généralement en lecture seule. Cependant, PostgreSQL permet de mettre à jour les tables sous-jacentes via une vue si certaines conditions sont remplies :

  1. La vue porte sur une seule table (pas de jointure, pas de sous-requête, pas de fonction d’agrégation).
  2. La vue n’utilise pas DISTINCT, GROUP BY, HAVING, UNION, etc.
  3. La vue inclut toutes les colonnes obligatoires (ex : NOT NULL sans défaut).
-- Vue simple sur une table
CREATE VIEW produits_view AS
SELECT id, nom, prix, stock FROM produits;
-- Mise à jour réussie
UPDATE produits_view SET prix = 899.99 WHERE id = 1;
UPDATE produits_view SET stock = stock + 5 WHERE id = 2;
INSERT INTO produits_view (nom, prix, stock, categorie_id)
VALUES ('Tablette', 399.99, 20, 1);
-- Vérification
SELECT * FROM produits_view;

⚠️ Attention : Les mises à jour via une vue ne sont pas toujours possibles. Pour les vues complexes, utilisez des déclencheurs (INSTEAD OF triggers) pour personnaliser les mises à jour.


Une vue matérialisée (ou materialized view) est une vue qui stocke physiquement les données sur le disque. Contrairement à une vue classique, les données sont figées au moment de la création ou d’un rafraîchissement.

CREATE MATERIALIZED VIEW nom_vue AS
SELECT colonnes
FROM tables
[WHERE condition];
-- Créer une vue matérialisée des produits les plus vendus
CREATE MATERIALIZED VIEW produits_populaires AS
SELECT
p.id,
p.nom,
p.prix,
COUNT(c.id) AS nb_commandes
FROM produits p
LEFT JOIN commandes c ON c.produit_id = p.id
GROUP BY p.id, p.nom, p.prix
HAVING COUNT(c.id) > 10;
-- Interroger la vue matérialisée
SELECT * FROM produits_populaires;
  • Performance : les données sont précalculées et stockées.
  • Possibilité d’index : vous pouvez créer des index sur la vue matérialisée.
  • Réduction de charge : les requêtes complexes ne sont pas réexécutées à chaque accès.
  • Données figées : la vue n’est pas automatiquement mise à jour quand les tables sources changent.
  • Maintenance : il faut périodiquement rafraîchir la vue avec REFRESH MATERIALIZED VIEW.
  • Espace disque : les données sont dupliquées.
-- Rafraîchir la vue (bloque les lectures pendant l'opération)
REFRESH MATERIALIZED VIEW produits_populaires;
-- Rafraîchir sans bloquer les lectures (CONCURRENTLY) - nécessite un index unique
REFRESH MATERIALIZED VIEW CONCURRENTLY produits_populaires;

⚠️ Bon à savoir : Pour utiliser REFRESH CONCURRENTLY, vous devez d’abord créer un index unique sur la vue matérialisée.

-- Créer un index pour accélérer les recherches
CREATE INDEX idx_produits_populaires_nom ON produits_populaires (nom);
-- Créer un index unique pour permettre le REFRESH CONCURRENTLY
CREATE UNIQUE INDEX idx_produits_populaires_id ON produits_populaires (id);

-- Vue des commandes avec détails client et produit
CREATE VIEW commandes_detail AS
SELECT
c.id AS commande_id,
cl.nom AS client,
cl.email AS client_email,
p.nom AS produit,
p.prix,
c.quantite,
c.montant_total,
c.date_commande
FROM commandes c
JOIN clients cl ON c.client_id = cl.id
JOIN produits p ON c.produit_id = p.id;

2. Vue pour la sécurité (masquage de colonnes)

Section titled “2. Vue pour la sécurité (masquage de colonnes)”
-- Vue qui masque les colonnes sensibles (salaire, numéro de sécurité sociale)
CREATE VIEW employes_public AS
SELECT id, nom, prenom, email, service
FROM employes;
-- Les colonnes 'salaire' et 'ssn' ne sont pas exposées

3. Vue matérialisée pour un rapport (BI)

Section titled “3. Vue matérialisée pour un rapport (BI)”
-- Rapport mensuel des ventes
CREATE MATERIALIZED VIEW rapport_ventes_mensuel AS
SELECT
DATE_TRUNC('month', date_commande) AS mois,
c.nom AS categorie,
SUM(ca.quantite) AS total_quantite,
SUM(ca.montant_total) AS chiffre_affaires
FROM commandes ca
JOIN produits p ON ca.produit_id = p.id
JOIN categories c ON p.categorie_id = c.id
GROUP BY mois, c.nom
ORDER BY mois DESC;
-- Rafraîchir chaque nuit
REFRESH MATERIALIZED VIEW rapport_ventes_mensuel;

Cas Recommandation
Requête simple, données fréquemment mises à jour Utilisez une vue classique.
Requête complexe, données figées dans le temps Utilisez une vue matérialisée.
Besoin de masquer des colonnes sensibles Utilisez une vue classique.
Rapports BI avec données agrégées Utilisez une vue matérialisée (rafraîchissement périodique).
Mise à jour via une vue Utilisez une vue classique simple (sans jointure).
Index nécessaire sur la vue Utilisez une vue matérialisée (les vues classiques ne peuvent pas être indexées directement).

Caractéristique Vue classique Vue matérialisée
Stockage des données Non (virtuelle) Oui (physique)
Toujours à jour Oui Non (nécessite rafraîchissement)
Performance Variable (exécute la requête) Excellente (données précalculées)
Indexation possible Non (mais les tables sous-jacentes peuvent être indexées) Oui
Mise à jour possible Oui (si conditions remplies) Non (directement)
Espace disque Aucun Occupe de l’espace
Rafraîchissement Automatique Manuel (REFRESH)

Action Commande
Créer une vue classique CREATE VIEW nom AS SELECT ...;
Modifier une vue CREATE OR REPLACE VIEW nom AS SELECT ...;
Supprimer une vue DROP VIEW nom;
Créer une vue matérialisée CREATE MATERIALIZED VIEW nom AS SELECT ...;
Rafraîchir une vue matérialisée REFRESH MATERIALIZED VIEW nom;
Rafraîchir sans bloquer REFRESH MATERIALIZED VIEW CONCURRENTLY nom;
Supprimer une vue matérialisée DROP MATERIALIZED VIEW nom;
Lister les vues \dv ou \dv+
Voir la définition d’une vue SELECT pg_get_viewdef('nom_vue'::regclass);

Vous savez maintenant créer et utiliser des vues classiques et matérialisées pour simplifier vos requêtes, améliorer les performances et gérer les droits. Dans le prochain cours, nous aborderons la gestion des utilisateurs et des rôles, un élément fondamental pour sécuriser votre base de données.

👉 Cours 8 : Utilisateurs et rôles


Junior TSAFACK – 20/08/2026