Présentation

Dans la plupart des SGBD-R, il existe un langage de programmation impératif classique qui permet d’écrire des successions d’opérations relationnelles en utilisant les possibilités habituelles de la programmation impérative type Pascal, C ou C++ (variable, affectation, tests,boucle, exception, procédure et fonction…).
PL-SQL est le nom générique de ce langage pour tous les SGBD. La syntaxe du PL-SQL est en partie standardisée.

Ce type de programme est très interessant pour :

Développer un Bloc simple PL/SQL

[ DECLARE ]
- Variables, constantes, curseurs,
exceptions utilisateurs
BEGIN
- Ordres SQL
- Instructions de Contrôle PL/SQL
[ EXCEPTION ]
- Traitements à effectuer lors d'erreurs
END ;

CM4 toulouse guillaume Cabanac : introduction PL/SQL

CM5 toulouse guillaume Cabanac : PL/SQL Exceptions et curseurs


Rappel 1: Variables et Affichage

Créez une variable nommée nom_utilisateur et initialisez-la avec votre nom. Affichez le contenu de la variable nom_utilisateur à l’aide d’une instruction SELECT.

-- Création de la variable
SET @nom_utilisateur = 'VotreNom';

-- Affichage de la variable
SELECT @nom_utilisateur AS NomUtilisateur;

Exercice 1: Procédures Stockées

Créez une procédure stockée nommée ajouter_utilisateur qui prend en paramètres le nom et l’âge d’un utilisateur, et insère ces informations dans une table utilisateurs. Appelez la procédure avec quelques exemples.

-- Création de la table utilisateurs
DROP TABLE IF EXISTS utilisateurs;
CREATE TABLE utilisateurs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nom VARCHAR(50),
    prenom VARCHAR(50),
    age INT,
    majeur INT
);

DROP PROCEDURE IF EXISTS AjouterUtilisateur;  
-- Création de la procédure stockée
DELIMITER //
CREATE PROCEDURE AjouterUtilisateur(IN nom_utilisateur VARCHAR(50), IN age_utilisateur INT)
BEGIN
    INSERT INTO utilisateurs (nom, age) VALUES (nom_utilisateur, age_utilisateur);
END //
DELIMITER ;

-- Appel de la procédure
CALL AjouterUtilisateur('John Doe', 25);
CALL AjouterUtilisateur('Jane Doe', 30);

-- Affichage du contenu de la table utilisateurs
SELECT * FROM utilisateurs;

Modifier la fonction AjouterUtilisateur pour mettre en majuscule le nom et en minuscule le prénom. (il faut modifier l’appel de la procédure et passer dans 2 paramètres distincts le nom et le prénom)

Exercice 2: Fonctions

Créez une fonction appelée calculer_moyenne qui prend en paramètre deux nombres et retourne leur moyenne. Utilisez la fonction pour calculer la moyenne de deux ensembles de nombres différents.


-- Création de la fonction
DELIMITER //
CREATE FUNCTION CalculerMoyenne(a INT, b INT)
RETURNS DECIMAL(5,2)
BEGIN
    DECLARE moyenne DECIMAL(5,2);
    SET moyenne = (a + b) / 2;
    RETURN moyenne;
END //
DELIMITER ;

-- Utilisation de la fonction
SELECT CalculerMoyenne(10, 20) AS MoyenneSet1;
SELECT CalculerMoyenne(5, 16.3333) AS MoyenneSet2;

DROP FUNCTION IF EXISTS CalculerMoyenne;

REMARQUE : erreur de droit sur MySQL(Oracle) sur la machine de l’iut :

Commande en tant que root : SET GLOBAL log_bin_trust_function_creators = 1;

Reprendre l’exercice, modifier le type des variables pour calculer la moyenne de 2 monétaires


Afficher les procédures

SELECT ROUTINE_NAME, ROUTINE_TYPE   
FROM information_schema.routines;

Exercice 3: Structures de Contrôle

Créez une procédure qui prend un paramètre en entrée (par exemple, age_utilisateur) et affiche “Majeur” si l’âge est supérieur ou égal à 18, sinon affiche “Mineur”. Testez la procédure en passant différentes valeurs à age_utilisateur.

DROP PROCEDURE IF EXISTS MiseAJourAge; 
-- Création de la procédure
DELIMITER //
CREATE PROCEDURE MiseAJourAge(IN age_utilisateur INT)
BEGIN
    IF age_utilisateur >= 18 THEN
        SELECT 'Majeur' AS Statut;
    ELSE
        SELECT 'Mineur' AS Statut;
    END IF;
END //
DELIMITER ;

-- Appel de la procédure
CALL MiseAJourAge(20);
CALL MiseAJourAge(15);

Modifier la fonction MiseAJourAge pour mettre à jour la colonne age et majeur de la table utilisateur. La procédure MiseAJourAge prend 2 paramètres en entrée : age_utilisateur et id_utilisateur, la colonne majeur de l’utilisateur vaut 1 si l’utilisateur est majeur et 0 sinon.

test :

-- test : Appel de la procédure
SELECT * FROM utilisateurs;
CALL MiseAJourAge(1,20);
CALL MiseAJourAge(2,15);
SELECT * FROM utilisateurs;

Exercice 4: Boucles

Créez une table nombres avec une colonne valeur. Utilisez une boucle pour insérer des valeurs de 1 à 10 dans la table. Affichez le contenu de la table nombres.

-- Création de la table
CREATE TABLE nombres (
    valeur INT
);
DROP PROCEDURE IF EXISTS RemplirNombres;

-- Insertion des valeurs de 1 à 10
DELIMITER //
CREATE PROCEDURE RemplirNombres()
BEGIN
    DECLARE i INT DEFAULT 1;
    WHILE i <= 10 DO
        INSERT INTO nombres (valeur) VALUES (i);
        SET i = i + 1;
    END WHILE;
END //
DELIMITER ;

-- Appel de la procédure
CALL RemplirNombres();

-- Affichage du contenu de la table
SELECT * FROM nombres;

Exercice 5: Déclencheurs (Triggers)

Créez une table historique_utilisateurs avec des colonnes telles que id_utilisateur, nom_utilisateur, action et date_action. Créez un déclencheur qui enregistre une nouvelle ligne dans historique_utilisateurs à chaque fois qu’un utilisateur est ajouté à la table utilisateurs.

-- Création de la table historique_utilisateurs
DROP TABLE IF EXISTS historique_utilisateurs;
CREATE TABLE historique_utilisateurs (
    id_utilisateur INT AUTO_INCREMENT PRIMARY KEY,
    nom_utilisateur VARCHAR(50),
    action VARCHAR(50)
);
DROP TRIGGER IF EXISTS  after_insert_utilisateur; 

-- Création du déclencheur
DELIMITER //
CREATE TRIGGER after_insert_utilisateur
AFTER INSERT ON utilisateurs
FOR EACH ROW
BEGIN
    INSERT INTO historique_utilisateurs (id_utilisateur, nom_utilisateur, action)
    VALUES (NEW.id, NEW.nom, 'Ajout');
END //
DELIMITER ;

-- Ajout d'un utilisateur pour déclencher le déclencheur
INSERT INTO utilisateurs (nom, age) VALUES ('lionel', 28);

-- Affichage du contenu de la table historique_utilisateurs
SELECT * FROM historique_utilisateurs;
SELECT * FROM utilisateurs;

Créer un nouveau “trigger” (déclencheur) pour mettre en majuscule le nom et en minuscule le prénom lors d’un INSERT

Exercice 6: exemple de curseurs

Un curseur est une structure de contrôle qui permet d’itérer à travers un ensemble de lignes renvoyées par une requête SQL. Il agit comme un pointeur sur un ensemble de résultats et permet de traiter chaque ligne de manière séquentielle.


-- procedure
-- https://dev.mysql.com/doc/refman/8.0/en/cursors.html
DROP PROCEDURE IF EXISTS testUtilisateurs ;
DELIMITER //
CREATE PROCEDURE testUtilisateurs()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE b CHAR(50);
  DECLARE a INT;
  DECLARE c INT;
  DECLARE d INT;
  DECLARE cur1 CURSOR FOR SELECT id,nom,age, majeur FROM utilisateurs;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
  OPEN cur1;
  read_loop: LOOP
    FETCH cur1 INTO a, b, c ,d;
    IF done THEN
      LEAVE read_loop;
    END IF;
    SELECT a,b,c,d ;   -- affichage
  END LOOP;
  CLOSE cur1;
END //
DELIMITER ;

ajouter un an à l’age de tous les utilisateurs dans la procédure ci-dessus

Test :

SELECT * FROM utilisateurs;
CALL testUtilisateurs();
SELECT * FROM utilisateurs;