CONSTRAINT fk_client FOREIGN KEY
DDL — Data Definition (id_client)
Language REFERENCES clients(id) ON DELETE
CASCADE ON UPDATE CASCADE,
CONSTRAINT fk_livre FOREIGN KEY
CREATE DATABASE (id_livre)
-- Créer une base de données REFERENCES livres(id) ON DELETE
CREATE DATABASE librairie; RESTRICT
);
-- Créer seulement si elle n'existe
pas déjà
CREATE DATABASE IF NOT EXISTS Table avec clé primaire composite
librairie -- Deux colonnes forment la clé
CHARACTER SET utf8mb4 primaire
COLLATE utf8mb4_unicode_ci; CREATE TABLE livre_categorie (
id_livre INT NOT NULL,
id_categorie INT NOT NULL,
PRIMARY KEY (id_livre,
USE id_categorie)
-- Sélectionner la base à utiliser );
USE librairie;
CREATE TABLE ... AS SELECT
-- Créer une table à partir d'une
CREATE TABLE requête existante
CREATE TABLE archives_clients AS
Table simple SELECT id, nom, email, solde FROM
-- Créer une table avec les types clients WHERE actif = FALSE;
courants
CREATE TABLE clients (
id INT CREATE TABLE ... LIKE
AUTO_INCREMENT PRIMARY KEY,
-- Copier la structure d'une table
nom VARCHAR(100) NOT NULL, (sans les données)
email VARCHAR(150) UNIQUE, CREATE TABLE clients_backup LIKE
telephone VARCHAR(20), clients;
solde DECIMAL(10,2) DEFAULT
0.00,
actif BOOLEAN DEFAULT
TRUE, ALTER TABLE
cree_le DATETIME DEFAULT
CURRENT_TIMESTAMP Ajouter une colonne
); -- Ajouter une colonne à la fin
ALTER TABLE clients ADD COLUMN ville
VARCHAR(100);
Table avec clé étrangère
-- Créer une table qui référence une -- Ajouter une colonne à une position
autre table précise
CREATE TABLE commandes ( ALTER TABLE clients ADD COLUMN
id INT date_naissance DATE AFTER nom;
AUTO_INCREMENT PRIMARY KEY,
id_client INT NOT NULL,
-- Ajouter une colonne en première
id_livre INT NOT NULL, position
quantite INT DEFAULT 1 ALTER TABLE clients ADD COLUMN
CHECK (quantite > 0), code_interne INT FIRST;
montant DECIMAL(10,2) NOT NULL,
date_cmd DATETIME DEFAULT
CURRENT_TIMESTAMP,
Modifier une colonne
-- Modifier le type ou les ALTER TABLE clients ALTER COLUMN
contraintes d'une colonne solde DROP DEFAULT;
ALTER TABLE clients MODIFY COLUMN
telephone VARCHAR(30) NOT NULL;
Renommer une table
-- Renommer ET modifier une colonne -- Renommer une table
en même temps ALTER TABLE clients RENAME TO
ALTER TABLE clients CHANGE COLUMN customers;
telephone tel VARCHAR(30);
-- Renommer uniquement une colonne Modifier le moteur de stockage
(MySQL 8+) -- Changer le moteur (InnoDB =
ALTER TABLE clients RENAME COLUMN transactions, MyISAM = lecture
ville TO adresse_ville; rapide)
ALTER TABLE logs ENGINE = MyISAM;
Supprimer une colonne
-- Supprimer une colonne (données CREATE INDEX
perdues définitivement)
ALTER TABLE clients DROP COLUMN Index simple
code_interne;
-- Accélérer les recherches sur une
colonne
CREATE INDEX idx_nom ON clients
Ajouter / Supprimer une contrainte (nom);
-- Ajouter une clé primaire
ALTER TABLE clients ADD PRIMARY KEY
(id); Index unique
-- Index + contrainte d'unicité
-- Ajouter une contrainte UNIQUE CREATE UNIQUE INDEX idx_email ON
ALTER TABLE clients ADD CONSTRAINT clients (email);
uq_email UNIQUE (email);
-- Ajouter une clé étrangère Index composite
ALTER TABLE commandes ADD CONSTRAINT -- Index sur plusieurs colonnes
fk_cli CREATE INDEX idx_nom_ville ON clients
FOREIGN KEY (id_client) REFERENCES (nom, adresse_ville);
clients(id);
-- Supprimer une clé étrangère Index FULLTEXT
ALTER TABLE commandes DROP FOREIGN -- Recherche plein texte dans des
KEY fk_cli; colonnes TEXT/VARCHAR
CREATE FULLTEXT INDEX idx_ft_titre ON
livres (titre, description);
-- Supprimer une contrainte UNIQUE
ALTER TABLE clients DROP INDEX
uq_email; -- Utilisation avec MATCH ... AGAINST
SELECT * FROM livres
-- Supprimer la clé primaire WHERE MATCH(titre, description)
AGAINST ('mysql avancé' IN BOOLEAN
ALTER TABLE clients DROP PRIMARY KEY;
MODE);
Modifier la valeur par défaut
Supprimer un index
-- Changer la valeur par défaut d'une
-- Supprimer un index (la table et
colonne
les données restent)
ALTER TABLE clients ALTER COLUMN
DROP INDEX idx_nom ON clients;
solde SET DEFAULT 100.00;
-- Supprimer la valeur par défaut Voir les index d'une table
-- Lister tous les index d'une table
SHOW INDEX FROM clients; -- Voir le code CREATE TABLE d'une
table existante
SHOW CREATE TABLE clients;
DROP
-- Lister toutes les bases de données
DROP TABLE SHOW DATABASES;
-- Supprimer une table et toutes ses
données
DROP TABLE commandes;
-- Supprimer sans erreur si la table
n'existe pas
DROP TABLE IF EXISTS commandes;
-- Supprimer plusieurs tables en une
fois
DROP TABLE IF EXISTS commandes,
historique, logs;
DROP DATABASE
-- Supprimer toute la base de données
DROP DATABASE IF EXISTS librairie;
TRUNCATE TABLE
-- Vider la table (garde la
structure, reset AUTO_INCREMENT)
TRUNCATE TABLE historique;
-- Différence avec DELETE : TRUNCATE
est plus rapide
-- mais ne peut pas être annulé avec
ROLLBACK
RENAME TABLE
-- Renommer une table
RENAME TABLE clients TO customers;
-- Renommer plusieurs tables en une
fois
RENAME TABLE clients TO customers,
livres TO books;
SHOW & DESCRIBE
-- Lister toutes les tables de la
base courante
SHOW TABLES;
-- Voir la structure d'une table
DESCRIBE clients;
DESC clients;
-- Toujours utiliser WHERE pour
DML — Data Manipulation éviter de modifier toute la table
Language UPDATE clients
SET email = 'nouveau@[Link]',
solde = 1000.00
INSERT WHERE id = 1;
Insérer une ligne (tous les champs)
-- Spécifier chaque colonne Mettre à jour avec calcul
INSERT INTO clients (nom, email, -- Utiliser la valeur actuelle dans
solde) le calcul
VALUES ('Ahmed Benali', UPDATE livres
'ahmed@[Link]', 500.00);
SET prix = prix * 1.10
WHERE auteur = 'Ahmed Alaoui';
Insérer plusieurs lignes
-- Plusieurs lignes en une seule Mettre à jour avec CASE
requête (plus rapide)
-- Valeur différente selon une
INSERT INTO livres (titre, auteur,
condition
prix, stock) VALUES
UPDATE livres
('MySQL Avancé', 'Hassan Alaoui',
45.00, 20), SET stock = CASE
('PHP Complet', 'Sara El WHEN stock < 5 THEN stock + 20
Idrissi', 38.50, 15), WHEN stock < 10 THEN stock + 10
('Python Pro', 'Youssef ELSE stock
Berrada', 52.00, 10); END;
INSERT ... SELECT UPDATE avec JOIN
-- Copier des données depuis une -- Mettre à jour en se basant sur une
autre table autre table
INSERT INTO archives_clients (nom, UPDATE clients c
email, solde) JOIN commandes co ON co.id_client =
SELECT nom, email, solde FROM [Link]
clients WHERE actif = FALSE; SET [Link] = [Link] - [Link]
WHERE [Link] = 'validée';
INSERT ... ON DUPLICATE KEY UPDATE
-- Insérer ou mettre à jour si la clé DELETE
existe déjà
INSERT INTO produits (code, nom, Supprimer une ligne précise
stock)
-- Toujours utiliser WHERE pour
VALUES ('P001', 'Cahier', 100)
éviter de vider toute la table
ON DUPLICATE KEY UPDATE stock = stock
DELETE FROM commandes WHERE id = 42;
+ 100;
Supprimer avec condition
INSERT IGNORE
-- Supprimer toutes les commandes
-- Insérer et ignorer les erreurs de
d'avant 2023
doublon silencieusement
DELETE FROM commandes
INSERT IGNORE INTO clients (email,
nom) WHERE date_cmd < '2023-01-01';
VALUES ('doublon@[Link]', 'Test');
DELETE avec JOIN
-- Supprimer les clients qui n'ont
UPDATE jamais commandé
DELETE c FROM clients c
Mettre à jour une ligne précise
LEFT JOIN commandes co ON
co.id_client = [Link]
WHERE [Link] IS NULL;
Supprimer toutes les lignes
-- Vide la table (plus lent que
TRUNCATE, mais compatible ROLLBACK)
DELETE FROM logs;
-- Opérateurs : = <> != > < >= <=
DQL — Data Query Language SELECT * FROM livres WHERE prix > 50;
SELECT * FROM clients WHERE solde <>
SELECT — Structure complète 0;
-- Ordre logique d'écriture d'un
SELECT
SELECT [DISTINCT] colonnes BETWEEN
FROM table -- Valeur dans un intervalle (inclus)
[JOIN autre_table ON condition] SELECT * FROM livres WHERE prix
[WHERE condition] BETWEEN 20 AND 60;
[GROUP BY colonne(s)]
[HAVING condition_sur_groupe]
[ORDER BY colonne [ASC|DESC]] IN
[LIMIT n OFFSET m]; -- Valeur dans une liste
SELECT * FROM clients WHERE id IN (1,
3, 7, 12);
SELECT simple
LIKE
Toutes les colonnes -- % = n'importe quels caractères, _
-- Sélectionner toutes les colonnes = un seul caractère
(déconseillé en production) SELECT * FROM clients WHERE nom LIKE
SELECT * FROM clients; 'A%';
SELECT * FROM clients WHERE email
LIKE '%@[Link]';
Colonnes spécifiques avec alias SELECT * FROM livres WHERE titre
-- Choisir les colonnes et leur LIKE '_ython%';
donner un nom d'affichage
SELECT nom AS 'Nom du client',
email, IS NULL / IS NOT NULL
solde AS 'Solde (DH)' -- Tester si une valeur est nulle
FROM clients; SELECT * FROM clients WHERE email IS
NULL;
SELECT * FROM clients WHERE email IS
Colonnes calculées NOT NULL;
-- Créer des colonnes avec des
calculs
SELECT titre, Combinaisons AND / OR / NOT
prix, -- Combiner plusieurs conditions
prix * 1.20 AS SELECT * FROM livres
prix_ttc, WHERE prix < 50 AND stock > 0 AND
prix * 0.90 AS auteur LIKE '%Alaoui%';
prix_remise,
CONCAT(titre,' — ',auteur) AS SELECT * FROM clients
fiche WHERE ville = 'Rabat' OR ville =
FROM livres; 'Casablanca';
SELECT DISTINCT
-- Supprimer les doublons dans les ORDER BY
résultats
SELECT DISTINCT auteur FROM livres; Tri croissant / décroissant
-- ASC = croissant (défaut), DESC =
décroissant
SELECT * FROM livres ORDER BY prix
WHERE — Filtres ASC;
SELECT * FROM clients ORDER BY nom
Comparaisons simples DESC;
HAVING total > 500
ORDER BY total DESC;
Tri sur plusieurs colonnes
-- Trier par nom d'abord, puis par
prénom
SELECT * FROM clients ORDER BY nom Sous-requêtes (Subqueries)
ASC, prenom ASC;
Sous-requête dans WHERE
-- Livres plus chers que la moyenne
SELECT titre, prix FROM livres
LIMIT & OFFSET WHERE prix > (SELECT AVG(prix) FROM
livres);
Limiter le nombre de résultats
-- Récupérer uniquement les 10
premiers résultats Sous-requête avec IN
SELECT * FROM livres ORDER BY prix -- Clients ayant au moins une
DESC LIMIT 10; commande
SELECT nom FROM clients
WHERE id IN (SELECT DISTINCT
Pagination id_client FROM commandes);
-- Page 3 : sauter les 20 premiers
(10 résultats par page)
SELECT * FROM clients ORDER BY nom Sous-requête dans FROM
LIMIT 10 OFFSET 20; -- Table dérivée : stats puis filtre
sur stats
SELECT dept, AVG(total) AS moy_achats
FROM (
GROUP BY & HAVING
SELECT id_client AS dept,
SUM(montant) AS total
Grouper et compter
FROM commandes GROUP BY id_client
-- Nombre de commandes par client
) AS stats
SELECT id_client, COUNT(*) AS
GROUP BY dept;
nb_commandes
FROM commandes
GROUP BY id_client;
EXISTS
-- Vrai si la sous-requête retourne
au moins une ligne
Grouper avec plusieurs fonctions
SELECT nom FROM clients c
-- Statistiques par client
WHERE EXISTS (
SELECT id_client,
SELECT 1 FROM commandes co
COUNT(*) AS
WHERE co.id_client = [Link]
nb_commandes,
);
SUM(montant) AS
total_achats,
AVG(montant) AS
panier_moyen,
MAX(montant) AS
plus_grosse_commande
FROM commandes
GROUP BY id_client
ORDER BY total_achats DESC;
HAVING — Filtrer les groupes
-- Clients ayant dépensé plus de 500
DH
SELECT id_client, SUM(montant) AS
total
FROM commandes
GROUP BY id_client
SELECT [Link] AS employe, [Link] AS
Jointures (JOINs) manager
FROM employes e
INNER JOIN LEFT JOIN employes m ON [Link] =
e.id_manager;
-- Retourne uniquement les lignes
avec correspondance dans les 2 tables
SELECT [Link], [Link], [Link]
FROM commandes co FULL OUTER JOIN (émulé avec
INNER JOIN clients c ON [Link] =
co.id_client
UNION)
INNER JOIN livres l ON [Link] = -- MySQL n'a pas FULL JOIN : on
co.id_livre; combine LEFT + RIGHT avec UNION
SELECT [Link], [Link] AS commande
FROM clients c LEFT JOIN commandes co
ON co.id_client = [Link]
LEFT JOIN UNION
-- Tous les clients, même ceux sans SELECT [Link], [Link] AS commande
commande (NULL si absent à droite) FROM clients c RIGHT JOIN commandes
SELECT [Link], COUNT([Link]) AS co ON co.id_client = [Link];
nb_commandes
FROM clients c
LEFT JOIN commandes co ON
co.id_client = [Link]
GROUP BY [Link], [Link];
-- Clients qui n'ont JAMAIS commandé
SELECT [Link] FROM clients c
LEFT JOIN commandes co ON
co.id_client = [Link]
WHERE [Link] IS NULL;
RIGHT JOIN
-- Tous les livres, même ceux jamais
commandés (NULL si absent à gauche)
SELECT [Link], COUNT([Link]) AS
nb_fois
FROM commandes co
RIGHT JOIN livres l ON [Link] =
co.id_livre
GROUP BY [Link], [Link];
CROSS JOIN
-- Toutes les combinaisons possibles
(produit cartésien)
SELECT [Link], [Link]
FROM clients c
CROSS JOIN livres l;
SELF JOIN
-- La table jointe sur elle-même (ex:
employé et son manager)
ALTER USER 'ahmed'@'localhost'
DCL — Data Control IDENTIFIED BY 'NouveauMDP!';
Language
-- Voir les droits d'un utilisateur
SHOW GRANTS FOR 'ahmed'@'localhost';
CREATE USER
-- Créer un utilisateur local
CREATE USER 'ahmed'@'localhost' -- Supprimer un utilisateur
IDENTIFIED BY 'MotDePasse123!'; DROP USER IF EXISTS
'ancien'@'localhost';
-- Créer un utilisateur accessible
depuis n'importe quelle machine -- Lister tous les utilisateurs
CREATE USER 'lecteur'@'%' IDENTIFIED SELECT user, host FROM [Link];
BY 'Lecture2024!';
GRANT — Accorder des droits
-- Tous les droits sur une base
GRANT ALL PRIVILEGES ON librairie.*
TO 'ahmed'@'localhost';
-- Droits spécifiques sur une base
GRANT SELECT, INSERT, UPDATE ON
librairie.*
TO 'lecteur'@'localhost';
-- Droit de lecture sur une table
précise
GRANT SELECT ON [Link] TO
'rapport'@'localhost';
-- Permettre de transmettre ses
droits à d'autres
GRANT SELECT ON librairie.* TO
'manager'@'%' WITH GRANT OPTION;
-- Appliquer les changements
immédiatement
FLUSH PRIVILEGES;
REVOKE — Retirer des droits
-- Retirer tous les droits
REVOKE ALL PRIVILEGES ON librairie.*
FROM 'lecteur'@'localhost';
-- Retirer un droit précis
REVOKE DELETE ON [Link]
FROM 'ahmed'@'localhost';
Gestion des utilisateurs
-- Modifier le mot de passe
TCL — Transaction Control
-- Valide : les 2 premières commandes
Language seulement
COMMIT;
START TRANSACTION / COMMIT /
ROLLBACK
-- Démarrer une transaction Autocommit
START TRANSACTION; -- Désactiver le commit automatique
pour la session
-- Valider toutes les modifications SET autocommit = 0;
COMMIT;
-- Réactiver (comportement par
défaut)
-- Annuler toutes les modifications
depuis START TRANSACTION SET autocommit = 1;
ROLLBACK;
-- Verrou exclusif : empêche 2
transactions de modifier la même
ligne
Transaction simple SELECT stock FROM livres WHERE id = 1
-- Exemple : achat d'un livre FOR UPDATE;
(débiter client + baisser stock)
START TRANSACTION; -- Verrou partagé : lecture permise,
modification bloquée
UPDATE clients SET solde = solde - SELECT stock FROM livres WHERE id = 1
45.00 WHERE id = 1; FOR SHARE;
UPDATE livres SET stock = stock -
1 WHERE id = 3;
INSERT INTO commandes (id_client,
id_livre, montant)
VALUES (1, 3, 45.00);
COMMIT;
-- En cas d'erreur dans l'application
:
-- ROLLBACK;
SAVEPOINT — Point de retour
partiel
-- Créer un point de retour nommé
START TRANSACTION;
INSERT INTO commandes (id_client,
id_livre) VALUES (1, 1);
SAVEPOINT apres_cmd1;
INSERT INTO commandes (id_client,
id_livre) VALUES (2, 2);
SAVEPOINT apres_cmd2;
-- Annuler seulement depuis
apres_cmd2
ROLLBACK TO apres_cmd2;
CREATE PROCEDURE appliquer_tva(INOUT
Procédures Stockées p_prix DECIMAL(8,2))
BEGIN
Créer et appeler une procédure SET p_prix = p_prix * 1.20;
END //
-- Procédure sans paramètre
DELIMITER ;
DELIMITER //
CREATE PROCEDURE lister_clients()
BEGIN SET @prix = 100.00;
SELECT id, nom, solde FROM clients CALL appliquer_tva(@prix);
ORDER BY nom; SELECT @prix;
END //
DELIMITER ;
Variables locales
-- Appel de la procédure
-- Déclarer et utiliser des variables
CALL lister_clients();
dans une procédure
DELIMITER //
CREATE PROCEDURE calcul_total(IN p_id
Paramètre IN INT, OUT p_msg VARCHAR(200))
BEGIN
-- IN : la procédure reçoit une
DECLARE v_nom VARCHAR(100);
valeur (lecture seule)
DECLARE v_total DECIMAL(10,2)
DELIMITER //
DEFAULT 0;
CREATE PROCEDURE info_client(IN p_id
INT)
BEGIN SELECT nom INTO v_nom FROM clients
SELECT nom, email, solde WHERE id = p_id;
FROM clients WHERE id = p_id; SELECT SUM(montant) INTO v_total
END // FROM commandes WHERE id_client =
DELIMITER ; p_id;
CALL info_client(1); SET p_msg = CONCAT(v_nom, ' a
dépensé ', v_total, ' DH');
END //
DELIMITER ;
Paramètre OUT
-- OUT : la procédure renvoie une
valeur
IF / ELSEIF / ELSE
DELIMITER //
CREATE PROCEDURE nb_commandes(IN p_id -- Structure conditionnelle
INT, OUT p_nb INT) IF v_stock = 0 THEN
BEGIN SET v_msg = 'Rupture de stock';
SELECT COUNT(*) INTO p_nb ELSEIF v_stock < 5 THEN
FROM commandes WHERE id_client = SET v_msg = 'Stock faible';
p_id; ELSE
END // SET v_msg = 'Stock disponible';
DELIMITER ; END IF;
CALL nb_commandes(1, @n);
SELECT @n; CASE
-- CASE selon la valeur d'une
variable
Paramètre INOUT CASE v_statut
WHEN 'A' THEN SET v_label =
-- INOUT : la procédure lit ET
'Actif';
modifie la valeur
WHEN 'I' THEN SET v_label =
DELIMITER //
'Inactif';
ELSE SET v_label = SET p_msg = 'Erreur SQL —
'Inconnu'; transaction annulée';
END CASE; END;
-- CASE selon des expressions -- Continuer sur un doublon (erreur
CASE 1062)
WHEN v_prix < 20 THEN SET v_cat = DECLARE CONTINUE HANDLER FOR 1062
'Eco'; SET p_msg = 'Doublon ignoré';
WHEN v_prix < 100 THEN SET v_cat =
'Standard'; -- Lever une erreur personnalisée
ELSE SET v_cat = IF p_quantite <= 0 THEN
'Premium';
SIGNAL SQLSTATE '45000'
END CASE;
SET MESSAGE_TEXT = 'La quantité
doit être > 0';
END IF;
WHILE
-- Boucle : condition testée AVANT
chaque itération Commandes de gestion
DECLARE v_i INT DEFAULT 1;
-- Lister toutes les procédures
WHILE v_i <= 5 DO
SHOW PROCEDURE STATUS WHERE Db =
INSERT INTO logs (msg) VALUES 'librairie';
(CONCAT('Iteration ', v_i));
SET v_i = v_i + 1;
END WHILE; -- Voir le code source d'une
procédure
SHOW CREATE PROCEDURE info_client;
REPEAT ... UNTIL -- Supprimer une procédure
-- Boucle : condition testée APRÈS DROP PROCEDURE IF EXISTS info_client;
(exécutée au moins 1 fois)
REPEAT
SET v_n = v_n + 1;
UPDATE livres SET stock = stock + 1
WHERE id = v_n;
UNTIL v_n >= 10 END REPEAT;
LOOP avec LEAVE et ITERATE
-- LEAVE = sortir, ITERATE = passer à
l'itération suivante
ma_boucle: LOOP
SET v_n = v_n + 1;
IF v_n = 3 THEN ITERATE ma_boucle;
END IF;
IF v_n >= 10 THEN LEAVE ma_boucle;
END IF;
INSERT INTO logs VALUES (v_n);
END LOOP;
Gestion des erreurs — HANDLER
-- Quitter la procédure sur toute
erreur SQL
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
-- Enregistrer les changements de
Triggers (Déclencheurs) solde client
DELIMITER //
BEFORE INSERT — Validation CREATE TRIGGER after_clients_update
AFTER UPDATE ON clients
-- Vérifier et corriger les données
avant insertion FOR EACH ROW
DELIMITER // BEGIN
CREATE TRIGGER before_livres_insert IF [Link] <> [Link] THEN
BEFORE INSERT ON livres INSERT INTO audit_soldes
FOR EACH ROW (id_client, ancien, nouveau,
difference, modifie_le)
BEGIN
VALUES ([Link], [Link],
-- Prix doit être positif
[Link], [Link] - [Link],
IF [Link] <= 0 THEN
NOW());
SIGNAL SQLSTATE '45000'
END IF;
SET MESSAGE_TEXT = 'Prix doit
END //
être > 0';
DELIMITER ;
END IF;
-- Normaliser le titre
SET [Link] = CONCAT( BEFORE DELETE — Archivage
UPPER(LEFT([Link], 1)), -- Archiver les données avant
LOWER(SUBSTRING([Link], 2)) suppression définitive
); DELIMITER //
CREATE TRIGGER before_clients_delete
-- Stock minimum = 0 BEFORE DELETE ON clients
IF [Link] < 0 THEN SET [Link] FOR EACH ROW
= 0; END IF; BEGIN
END // INSERT INTO archives_clients
DELIMITER ; (id_original, nom, solde, archive_le)
VALUES ([Link], [Link], [Link],
NOW());
END //
AFTER INSERT — Journalisation DELIMITER ;
-- Réagir après une insertion :
mettre à jour le stock
DELIMITER //
CREATE TRIGGER after_commandes_insert
Commandes de gestion
AFTER INSERT ON commandes -- Lister tous les triggers
FOR EACH ROW SHOW TRIGGERS FROM librairie;
BEGIN
-- Décrémenter le stock du livre -- Voir le code source d'un trigger
UPDATE livres SHOW CREATE TRIGGER
SET stock = stock - [Link] after_commandes_insert;
WHERE id = NEW.id_livre;
-- Supprimer un trigger
-- Enregistrer dans l'historique DROP TRIGGER IF EXISTS
INSERT INTO historique (operation, before_livres_insert;
detail, fait_le)
VALUES ('COMMANDE', CONCAT('Cmd #',
[Link]), NOW());
END //
DELIMITER ;
AFTER UPDATE — Audit
SET prix = v_prix * (1 + p_pct /
Curseurs 100.0)
WHERE id = v_id;
Les 4 étapes obligatoires END LOOP;
-- 1. Déclarer le curseur
DECLARE cur_livres CURSOR FOR CLOSE cur;
SELECT id, prix FROM livres WHERE END //
stock > 0; DELIMITER ;
-- 2. Handler NOT FOUND — OBLIGATOIRE -- Augmenter tous les prix de 10%
DECLARE CONTINUE HANDLER FOR NOT CALL maj_prix(10);
FOUND SET v_fini = 1;
-- 3. Ouvrir le curseur (exécute la Curseur avec compteur OUT
requête)
OPEN cur_livres; -- Compter les lignes traitées et les
retourner
DELIMITER //
-- 4. Lire ligne par ligne CREATE PROCEDURE rapport_stock(IN
FETCH cur_livres INTO v_id, v_prix; p_seuil INT, OUT p_nb INT)
BEGIN
-- 5. Fermer le curseur DECLARE v_id INT;
CLOSE cur_livres; DECLARE v_stock INT;
DECLARE v_fini INT DEFAULT 0;
DECLARE v_cpt INT DEFAULT 0;
Curseur complet — Mise à jour prix
DECLARE cur CURSOR FOR SELECT id,
-- Parcourir chaque livre et stock FROM livres;
augmenter son prix DECLARE CONTINUE HANDLER FOR NOT
DELIMITER // FOUND SET v_fini = 1;
CREATE PROCEDURE maj_prix(IN p_pct
INT)
BEGIN OPEN cur;
DECLARE v_id INT; boucle: LOOP
DECLARE v_prix DECIMAL(8,2); FETCH cur INTO v_id, v_stock;
DECLARE v_fini INT DEFAULT 0; IF v_fini = 1 THEN LEAVE boucle;
END IF;
DECLARE cur CURSOR FOR
IF v_stock < p_seuil THEN
SELECT id, prix FROM livres WHERE
stock > 0; INSERT INTO alertes (id_livre,
stock) VALUES (v_id, v_stock);
SET v_cpt = v_cpt + 1;
DECLARE CONTINUE HANDLER FOR NOT END IF;
FOUND END LOOP;
SET v_fini = 1; CLOSE cur;
OPEN cur; SET p_nb = v_cpt;
END //
lecture: LOOP DELIMITER ;
FETCH cur INTO v_id, v_prix;
IF v_fini = 1 THEN LEAVE lecture; CALL rapport_stock(5, @nb_alertes);
END IF;
SELECT @nb_alertes AS 'Livres en
rupture';
UPDATE livres