🔧
Procédures vs Fonctions
Organiser et réutiliser ton code SQL
En PL/pgSQL, tu peux créer des procédures et des fonctions pour encapsuler de la logique réutilisable. La différence principale ?
📦 PROCEDURE
- ❌ Ne retourne rien (void)
- ✅ Peut avoir des paramètres OUT
- ✅ Peut faire COMMIT/ROLLBACK
- 📌 Appelée avec
CALL
⚡ FUNCTION
- ✅ Retourne une valeur
- ❌ Pas de COMMIT/ROLLBACK
- ✅ Utilisable dans SELECT
- 📌 Appelée directement ou dans une expression
💡 Règle simple
Fonction = Tu veux calculer et retourner quelque chose
Procédure = Tu veux exécuter des actions (INSERT, UPDATE, DELETE...)
Le trajet de la donnée
Clique sur un bouton : observe ce qui revient (ou pas) vers l'appelant.
Choisis un trajet : la fonction rend une valeur, la procédure exécute des actions.
⚡ Créer une Fonction
CREATE OR REPLACE FUNCTION calculer_ttc(prix NUMERIC, tva NUMERIC DEFAULT 0.20)
RETURNS NUMERIC
AS $$
BEGIN
RETURN prix * (1 + tva);
END;
$$ LANGUAGE plpgsql;
Utilisation :
-- Dans un SELECT
SELECT nom, calculer_ttc(prix) AS prix_ttc FROM produits;
-- Affectation à une variable
v_total := calculer_ttc(100, 0.10); -- 110
-- Appel direct
SELECT calculer_ttc(50); -- 60
⚠️ Points importants
- •
RETURNSdéfinit le type de retour - •
RETURN(sans S) renvoie la valeur - • Paramètres avec valeurs par défaut :
DEFAULT - •
$$ ... $$= délimiteurs du corps
📦 Créer une Procédure
CREATE OR REPLACE PROCEDURE augmenter_salaire(
p_employe_id INTEGER,
p_pourcentage NUMERIC
)
AS $$
BEGIN
UPDATE employes
SET salaire = salaire * (1 + p_pourcentage / 100)
WHERE id = p_employe_id;
RAISE NOTICE 'Salaire augmenté de %', p_pourcentage || '%';
END;
$$ LANGUAGE plpgsql;
Utilisation :
-- Appel avec CALL (obligatoire pour les procédures)
CALL augmenter_salaire(42, 10);
-- Avec paramètres nommés
CALL augmenter_salaire(p_employe_id => 42, p_pourcentage => 10);
↔️ Types de Paramètres
IN (défaut)
Lecture seule, ne peut pas être modifié
p_id IN INTEGER
OUT
Écriture seule, retourné à l'appelant
p_result OUT INTEGER
INOUT
Lecture + écriture
p_counter INOUT INTEGER
Exemple avec OUT :
CREATE OR REPLACE PROCEDURE get_employee_info(
p_id IN INTEGER,
p_name OUT VARCHAR,
p_salary OUT NUMERIC
)
AS $$
BEGIN
SELECT nom, salaire INTO p_name, p_salary
FROM employes WHERE id = p_id;
END;
$$ LANGUAGE plpgsql;
-- Appel
CALL get_employee_info(42, NULL, NULL);
-- Retourne les valeurs dans les paramètres OUT
Le sens de circulation des paramètres
Choisis un mode : regarde dans quel sens la valeur voyage entre l'appelant et la procédure.
🛠️ Exemples Pratiques
1. Fonction avec gestion d'erreur
CREATE OR REPLACE FUNCTION diviser(a NUMERIC, b NUMERIC)
RETURNS NUMERIC AS $$
BEGIN
IF b = 0 THEN
RAISE EXCEPTION 'Division par zéro interdite !';
END IF;
RETURN a / b;
EXCEPTION
WHEN OTHERS THEN
RAISE NOTICE 'Erreur: %', SQLERRM;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
2. Fonction retournant une table
CREATE OR REPLACE FUNCTION get_top_salaries(n INTEGER)
RETURNS TABLE(nom VARCHAR, salaire NUMERIC) AS $$
BEGIN
RETURN QUERY
SELECT e.nom, e.salaire
FROM employes e
ORDER BY e.salaire DESC
LIMIT n;
END;
$$ LANGUAGE plpgsql;
-- Utilisation
SELECT * FROM get_top_salaries(5);
3. Procédure avec transaction
CREATE OR REPLACE PROCEDURE transferer_fonds(
p_from INTEGER,
p_to INTEGER,
p_montant NUMERIC
)
AS $$
BEGIN
-- Débiter le compte source
UPDATE comptes SET solde = solde - p_montant WHERE id = p_from;
-- Créditer le compte destination
UPDATE comptes SET solde = solde + p_montant WHERE id = p_to;
-- Commit explicite (uniquement dans procédure)
COMMIT;
RAISE NOTICE 'Transfert de % effectué', p_montant;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
RAISE;
END;
$$ LANGUAGE plpgsql;
✨ Bonnes Pratiques
✅ À faire
- • Préfixer les paramètres (
p_) - • Préfixer les variables (
v_) - • Utiliser
%TYPEet%ROWTYPE - • Gérer les exceptions
- • Documenter avec des commentaires
❌ À éviter
- • Modifier un paramètre IN
- • Oublier le
;après RETURN - • SELECT sans INTO dans une fonction
- • COMMIT/ROLLBACK dans une fonction
- • Boucles infinies (oublier l'incrémentation)
🎯 Quiz - Teste tes connaissances !
🎉