Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

Chapitre 1112 minDébutant

Vues SQL : CREATE VIEW

Par Josselyn C., prof de BTS SIO. Mis à jour le .

À la fin de ce chapitre, tu sauras

  • créer, remplacer et supprimer une vue ;
  • simplifier des requêtes répétées grâce à une vue ;
  • restreindre l'accès aux données avec une vue ;
  • savoir quand une vue est modifiable.

3 exercices corrigés

Une vue SQL est une requête SELECT enregistrée dans la base sous un nom, avec CREATE VIEW. On l'interroge comme une table, mais elle ne stocke pas de données : chaque fois que tu l'utilises, le SGBD exécute la requête qui la définit, sur les données du moment. Les exemples créent des vues sur la base d'exemple parc ; le chapitre GRANT, REVOKE et rôles s'en sert ensuite pour restreindre l'accès.

Créer, remplacer, supprimer

sql
CREATE VIEW v_ticket_detail AS
SELECT t.id_ticket, t.titre, t.priorite, t.statut, t.date_ouverture, t.date_cloture,
       CONCAT(e.prenom, ' ', e.nom) AS demandeur,
       s.libelle AS service,
       p.num_inventaire
FROM ticket t
JOIN employe e    ON e.id_employe = t.id_demandeur
JOIN service s    ON s.id_service = e.id_service
LEFT JOIN poste p ON p.id_poste   = t.id_poste;

La vue s'utilise ensuite comme une table, avec ses propres filtres :

sql
SELECT id_ticket, titre, demandeur
FROM v_ticket_detail
WHERE statut <> 'resolu' AND service = 'Logistique'
ORDER BY id_ticket;
id_tickettitredemandeur
6Ventilateur bruyantLucas Girard
12Clavier casséLéa Rousseau
13Lenteurs réseau à l'entrepôtNadia Faure

Pour la modifier, CREATE OR REPLACE VIEW v_ticket_detail AS ... (ou ALTER VIEW) remplace sa définition. DROP VIEW IF EXISTS v_ticket_detail; la supprime, sans toucher aux tables. SHOW CREATE VIEW v_ticket_detail; affiche sa définition, et SHOW FULL TABLES; distingue les vues (VIEW) des tables (BASE TABLE).

Simplifier les requêtes

Une vue cache la complexité : les jointures, les calculs et les agrégats sont écrits une fois, testés une fois, et chacun s'en sert sans les réécrire. La charge de travail de chaque technicien :

sql
CREATE VIEW v_charge_technicien AS
SELECT e.id_employe,
       CONCAT(e.prenom, ' ', e.nom) AS technicien,
       COUNT(*)       AS nb_interventions,
       SUM(i.duree_min) AS minutes
FROM employe e
JOIN intervention i ON i.id_technicien = e.id_employe
GROUP BY e.id_employe, e.prenom, e.nom;
sql
SELECT technicien, nb_interventions, minutes
FROM v_charge_technicien
ORDER BY minutes DESC;
techniciennb_interventionsminutes
Antoine Mercier4510
Moussa Diallo7450
Chloé Lambert6295

Un tableau de bord, une application ou un outil de reporting lisent la vue ; si la règle de calcul change, tu modifies la vue et tous en profitent.

Restreindre l'accès

Une vue montre certaines colonnes et certaines lignes. L'annuaire interne affiche le nom, l'email, la ligne directe et le service de chacun, mais il n'a pas à montrer les dates d'embauche ni la hiérarchie ; si la table reçoit l'IBAN chiffré des salariés, l'annuaire ne doit jamais l'exposer :

sql
CREATE VIEW v_annuaire AS
SELECT e.nom, e.prenom, e.email, e.telephone, s.libelle AS service
FROM employe e
JOIN service s ON s.id_service = e.id_service;

Le responsable logistique ne doit voir que les tickets de son service :

sql
CREATE VIEW v_tickets_logistique AS
SELECT t.id_ticket, t.titre, t.priorite, t.statut, t.date_ouverture
FROM ticket t
JOIN employe e ON e.id_employe = t.id_demandeur
JOIN service s ON s.id_service = e.id_service
WHERE s.code = 'LOGI';

Rassembler plusieurs sources avec UNION

C'est la vue que les sujets d'E7 SLAM donnent souvent à lire ou à écrire : elle met bout à bout des lignes venues de tables de structures différentes. Le journal d'activité des tickets réunit les ouvertures (table ticket) et les interventions (table intervention). Une ouverture n'a pas de durée : la colonne est remplacée par NULL, pour que les deux SELECT aient le même nombre de colonnes.

sql
CREATE VIEW v_journal AS
SELECT t.id_ticket, t.date_ouverture AS moment, 'ouverture' AS evenement,
       t.id_demandeur AS id_employe, NULL AS duree_min
FROM ticket t
UNION ALL
SELECT i.id_ticket, i.date_intervention, 'intervention', i.id_technicien, i.duree_min
FROM intervention i;

SELECT v.moment, v.evenement, e.nom, v.duree_min
FROM v_journal v
JOIN employe e ON e.id_employe = v.id_employe
WHERE v.id_ticket = 9
ORDER BY v.moment;
momentevenementnomduree_min
2026-10-05 08:05:00ouvertureFaureNULL
2026-10-05 08:20:00interventionMercier240
2026-10-05 13:30:00interventionDiallo180
2026-10-06 09:00:00interventionLambert150

Les noms des colonnes de la vue viennent du premier SELECT, d'où les alias écrits là. La vue compte 31 lignes (14 ouvertures et 17 interventions), et elle n'est pas modifiable : un UPDATE ne saurait pas dans quelle table écrire.

Vues modifiables et WITH CHECK OPTION

On peut faire un UPDATE, un INSERT ou un DELETE à travers une vue, à condition que chaque ligne de la vue corresponde à une seule ligne d'une table. Une vue n'est pas modifiable si elle contient un agrégat ou une fonction de fenêtrage, DISTINCT, GROUP BY, HAVING, UNION, une sous-requête dans le SELECT, ou une jointure externe. Avec une jointure interne, on ne peut modifier qu'une table à la fois. Et une colonne calculée, comme demandeur dans v_ticket_detail, ne se modifie jamais.

Une vue sur les tickets en attente :

sql
CREATE VIEW v_tickets_en_attente AS
SELECT id_ticket, titre, priorite, statut, date_cloture
FROM ticket
WHERE statut <> 'resolu'
WITH CHECK OPTION;
sql
-- Accepté : le ticket 12 reste en attente
UPDATE v_tickets_en_attente SET priorite = 'normale' WHERE id_ticket = 12;

-- Refusé : la ligne sortirait de la vue
UPDATE v_tickets_en_attente
SET statut = 'resolu', date_cloture = '2026-10-28 11:00:00'
WHERE id_ticket = 12;
text
ERROR 1369 (HY000): CHECK OPTION failed 'parc.v_tickets_en_attente'

WITH CHECK OPTION interdit toute modification qui ferait sortir une ligne de la vue. Sans elle, le second UPDATE réussirait et le ticket disparaîtrait de la vue de celui qui vient de le modifier. Quand une vue repose sur une autre vue, WITH CASCADED CHECK OPTION (le comportement par défaut) vérifie aussi les conditions des vues sous-jacentes ; WITH LOCAL CHECK OPTION ne vérifie que la vue elle-même.

Limites

  • Pas plus rapide. Une vue ne stocke rien : la requête sous-jacente s'exécute à chaque appel. MySQL fusionne si possible la vue dans ta requête (algorithme MERGE) ; sinon, il calcule son résultat dans une table temporaire (TEMPTABLE), par exemple pour une vue avec GROUP BY.
  • Définition figée. Un SELECT * dans une vue est développé à la création : une colonne ajoutée ensuite à la table n'apparaît pas, et une colonne supprimée rend la vue inutilisable. Nomme les colonnes.
  • Pas de paramètre. Une vue ne prend pas d'argument : le filtre se fait dans la requête qui l'utilise.
  • Vues sur vues. Empiler les vues rend les performances et les erreurs difficiles à comprendre. Deux niveaux, c'est déjà beaucoup.
  • Pas de vue matérialisée en MySQL ou MariaDB. PostgreSQL et Oracle proposent CREATE MATERIALIZED VIEW, qui stocke le résultat et le rafraîchit à la demande ; en MySQL, on l'imite avec une table remplie par un évènement planifié ou des triggers.

Exercices

Exercice 1 sur 3 La vue du parc Réussi À revoir

Crée une vue v_parc qui affiche pour chaque poste, y compris ceux en stock : le numéro d'inventaire, le type, la marque, le modèle, le prénom et le nom de l'utilisateur dans une colonne utilisateur (en stock sinon) et le libellé de son service dans une colonne service.

Voir la réponseMasquer la réponse de l'exercice 1
sql
CREATE VIEW v_parc AS
SELECT p.num_inventaire, p.type_poste, p.marque, p.modele,
       COALESCE(CONCAT(e.prenom, ' ', e.nom), 'en stock') AS utilisateur,
       s.libelle AS service
FROM poste p
LEFT JOIN employe e ON e.id_employe = p.id_employe
LEFT JOIN service s ON s.id_service = e.id_service;

Le second LEFT JOIN est indispensable : avec un JOIN, les postes en stock, qui n'ont pas d'employé donc pas de service, disparaîtraient.

Tu avais trouvé ?

Exercice 2 sur 3 Utiliser la vue Réussi À revoir

À partir de v_parc seulement, affiche le nombre de postes par service, avec une ligne stock pour les postes non affectés, du plus grand nombre au plus petit.

Voir la réponseMasquer la réponse de l'exercice 2
sql
SELECT COALESCE(service, 'stock') AS service, COUNT(*) AS nb_postes
FROM v_parc
GROUP BY service
ORDER BY nb_postes DESC, service;
servicenb_postes
Commercial4
Informatique3
Logistique3
Comptabilité2
stock2
Direction1

GROUP BY service porte sur la colonne de la vue : les deux postes en stock, dont le service vaut NULL, forment un groupe. MySQL accepte l'alias service dans l'ORDER BY ; il désigne ici la colonne calculée par COALESCE.

Tu avais trouvé ?

Exercice 3 sur 3 Modifiable ou non Réussi À revoir

Pour chacune des vues v_ticket_detail, v_charge_technicien et v_tickets_en_attente, dis si l'instruction suivante est acceptée, et pourquoi.

  1. UPDATE v_ticket_detail SET priorite = 'haute' WHERE id_ticket = 14;
  2. UPDATE v_ticket_detail SET demandeur = 'H. Garnier' WHERE id_ticket = 14;
  3. UPDATE v_charge_technicien SET minutes = 0 WHERE id_employe = 11;
  4. DELETE FROM v_tickets_en_attente WHERE id_ticket = 14;
Voir la réponseMasquer la réponse de l'exercice 3
  1. Refusée. v_ticket_detail contient un LEFT JOIN vers poste : une jointure externe rend la vue non modifiable. Avec un JOIN interne à cet endroit, l'instruction serait acceptée, car priorite vient de la seule table ticket.
  2. Refusée dans tous les cas : demandeur est calculée par CONCAT, elle ne correspond à aucune colonne d'une table.
  3. Refusée : la vue contient GROUP BY et des agrégats. Une ligne de la vue résume plusieurs interventions ; quelle ligne modifier ?
  4. Acceptée : la vue porte sur une seule table, sans agrégat. Le ticket 14 est supprimé de la table ticket, et ses interventions éventuelles avec lui (clé étrangère en CASCADE).

Tu avais trouvé ?

Chapitre terminé !

Fais les 3 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Chapitre suivant : Index SQL et EXPLAINRevoir le sommaire du cours