Aller au contenu

Procédures stockées

Une procédure stockée est un ensemble d'instructions SQL enregistrées sur le serveur MySQL, qui peuvent être réutilisées. Contrairement à une fonction, une procédure stockée peut retourner un ou plusieurs jeux de résultats.

Création d'une procédure

Syntaxe de base

DELIMITER $$

CREATE PROCEDURE nom_procedure()
BEGIN
  -- Traitement
END $$

DELIMITER ;

Paramètres

Les paramètres d'une procédure sont définis par leur nom, leur type de données et leur mode (IN, OUT, ou INOUT) :

  • IN : Le paramètre est passé à la procédure et utilisé pour les calculs internes.
  • OUT : La procédure peut modifier ce paramètre pour retourner une valeur.
  • INOUT : Combinant les modes IN et OUT, ce paramètre peut être modifié et lu.
  • Par défaut, un paramètre est considéré comme IN si aucun mode n'est spécifié.
  • Les paramètres doivent être séparés par des virgules.

Traitement

  • Une procédure stockée peut mais n'est pas obligée de retourner une valeur. Elle peut effectuer diverses opérations, comme supprimer des enregistrements suivant certains critères.
  • Il est conseillé de retourner un indicateur de succès ou d'erreur pour signaler l'issue de la procédure.
  • Les gestionnaires d'erreurs (HANDLERs) peuvent être utilisés pour contrôler le traitement et gérer les exceptions.

Utilisation de variables

Les variables dans une procédure sont déclarées comme suit :

DECLARE nom_variable type_de_donnee [DEFAULT valeur_default];
  • DEFAULT est optionnel et permet d'assigner une valeur initiale à la variable.

Exemples d'utilisation de variables :

DECLARE prenom VARCHAR(50) DEFAULT 'Lucien';

SET prenom = 'Paul';

SELECT u.prenom INTO prenom
FROM usager u
WHERE u.id = 1234;
  • Les variables peuvent être assignées directement avec SET ou via un SELECT ... INTO, qui doit retourner une valeur unique.

Suppression d'une procédure

Pour supprimer une procédure stockée, utilisez :

DROP PROCEDURE [IF EXISTS] nom_procedure;

Utilisation de transactions dans une procédure stockée.

Une des utilisations de procédures stockées est de regrouper des opérations dans une transaction. Cela permet de garantir l'intégrité des données en cas d'erreur. L'uitilisation de transactions dans une procédure stockée est similaire à celle dans un script SQL.

Ex:

Prenons la table compte suivante :

CREATE TABLE compte (
  id INT PRIMARY KEY,
  solde DECIMAL(10,2)
);

INSERT INTO compte (id, solde) VALUES (1, 1000.00);
INSERT INTO compte (id, solde) VALUES (2, 500.00);

Nous voulons créer une procédure transfert_fonds qui transfère un montant d'un compte à un autre. Voici un exemple de procédure qui effectue cette opération :

DELIMITER $$

CREATE PROCEDURE transfert_fonds(
    IN id_source INT, 
    IN id_destination INT, 
    IN montant DECIMAL(10,2)
)
BEGIN
    -- Déclaration des variables pour la gestion d'erreur
    DECLARE error_message TEXT;
    DECLARE sql_state CHAR(5) DEFAULT '';

    -- Variable de travail
    DECLARE solde_source DECIMAL(10,2);


    DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN
        -- Rollback de la transaction
        ROLLBACK;

        -- Extraire les informations d'erreur
        GET STACKED DIAGNOSTICS CONDITION 1
            error_message = MESSAGE_TEXT,
            sql_state = RETURNED_SQLSTATE;

        -- Afficher le message d'erreur
        SELECT sql_state,
            error_message AS message_erreur;
    END;

    START TRANSACTION;

    -- Extraire le solde du compte source
    SELECT solde INTO solde_source
    FROM compte
    WHERE id = id_source
    FOR UPDATE; -- Optional: Pour barrer l'enregistrement pour éviter la concurence (race condition)

    -- Vérifier si le compte existe
    IF solde_source IS NULL THEN
        SIGNAL SQLSTATE '45000' 
            SET MESSAGE_TEXT = 'Compte source inexistant';
    END IF;

    -- Vérifier si le solde du compte source est suffisant
    IF solde_source < montant THEN
        SIGNAL SQLSTATE '45000' 
            SET MESSAGE_TEXT = 'Solde insuffisant';
    END IF;

    -- Enlever le montant du compte source
    UPDATE compte
    SET solde = solde - montant
    WHERE id = id_source;

    -- Ajouter le montant au compte de destination
    UPDATE compte
    SET solde = solde + montant
    WHERE id = id_destination;

    -- Vérifier si le compte de destination existe
    IF ROW_COUNT() = 0 THEN
        SIGNAL SQLSTATE '45000' 
            SET MESSAGE_TEXT = 'Compte destination inexistant';
    END IF;

    -- Transaction réussie!
    COMMIT;

    -- Message pour indiquer que le transfert est réussi
    SELECT 'Transfert réussi' AS message_succes;
END $$
DELIMITER ;

Ressources