Cette page reprend les bases de PL/pgSQL pour un profil déjà à l'aise avec Oracle PL/SQL : blocs, variables, fonctions, procédures, curseurs, exceptions et triggers, avec des points de comparaison utiles pour retrouver vite ses repères.
DO $$
DECLARE
v_nom TEXT;
v_salaire NUMERIC;
BEGIN
SELECT first_name, salary
INTO v_nom, v_salaire
FROM employees
WHERE employee_id = 100;
RAISE NOTICE 'Nom: %, Salaire: %', v_nom, v_salaire;
EXCEPTION
WHEN no_data_found THEN
RAISE NOTICE 'Employé introuvable';
WHEN OTHERS THEN
RAISE NOTICE 'Erreur: %', SQLERRM;
END $$;
Le parallèle Oracle est direct : DECLARE, BEGIN, EXCEPTION restent vos repères. La sortie de debug passe souvent par RAISE NOTICE au lieu de DBMS_OUTPUT.PUT_LINE.
DO $$
DECLARE
v_nombre INTEGER := 10;
v_texte TEXT := 'Hello';
v_date TIMESTAMP := CURRENT_TIMESTAMP;
v_nom employees.first_name%TYPE;
v_ligne employees%ROWTYPE;
BEGIN
SELECT *
INTO v_ligne
FROM employees
WHERE employee_id = 100;
v_nom := v_ligne.first_name;
RAISE NOTICE 'Nom: %', v_nom;
END $$;
Les ancres %TYPE et %ROWTYPE existent aussi en PL/pgSQL, ce qui facilite beaucoup la transition depuis Oracle.
DO $$
DECLARE
v_salaire NUMERIC := 5000;
v_bonus NUMERIC;
i INTEGER;
BEGIN
IF v_salaire > 10000 THEN
v_bonus := v_salaire * 0.15;
ELSIF v_salaire > 5000 THEN
v_bonus := v_salaire * 0.10;
ELSE
v_bonus := v_salaire * 0.05;
END IF;
FOR i IN 1..5 LOOP
RAISE NOTICE 'Iteration %', i;
END LOOP;
WHILE v_bonus < 1000 LOOP
v_bonus := v_bonus + 100;
END LOOP;
END $$;
CREATE OR REPLACE FUNCTION fn_bonus(p_salaire NUMERIC)
RETURNS NUMERIC
LANGUAGE plpgsql
AS $$
DECLARE
v_bonus NUMERIC;
BEGIN
IF p_salaire > 10000 THEN
v_bonus := p_salaire * 0.15;
ELSIF p_salaire > 5000 THEN
v_bonus := p_salaire * 0.10;
ELSE
v_bonus := p_salaire * 0.05;
END IF;
RETURN v_bonus;
END;
$$;
SELECT fn_bonus(7000);
En PostgreSQL, les fonctions sont très centrales. Historiquement, elles ont souvent été plus utilisées que les procédures.
CREATE OR REPLACE PROCEDURE maj_salaires(p_dept_id INTEGER, p_taux NUMERIC)
LANGUAGE plpgsql
AS $$
BEGIN
UPDATE employees
SET salary = salary * (1 + p_taux)
WHERE department_id = p_dept_id;
END;
$$;
CALL maj_salaires(10, 0.05);
Le parallèle Oracle procédure reste naturel. Retenez surtout la syntaxe CALL pour l'exécution d'une procédure.
DO $$
DECLARE
emp_rec RECORD;
BEGIN
FOR emp_rec IN
SELECT employee_id, first_name, salary
FROM employees
WHERE department_id = 50
LOOP
RAISE NOTICE '% - %', emp_rec.first_name, emp_rec.salary;
END LOOP;
END $$;
Comme en Oracle, vous pouvez ouvrir des curseurs explicites, mais le parcours en boucle FOR ... IN SELECT reste souvent le plus lisible pour les cas courants.
DO $$
BEGIN
PERFORM 1 / 0;
EXCEPTION
WHEN division_by_zero THEN
RAISE NOTICE 'Division par zéro détectée';
WHEN OTHERS THEN
RAISE NOTICE 'Erreur: %', SQLERRM;
END $$;
Le schéma mental reste proche d'Oracle. Vous gagnez à mémoriser quelques noms d'exceptions PostgreSQL, puis à garder un traitement WHEN OTHERS propre pour la journalisation.
CREATE OR REPLACE FUNCTION trg_factures_audit()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
NEW.statut := UPPER(NEW.statut);
RETURN NEW;
END;
$$;
CREATE TRIGGER before_factures_insert
BEFORE INSERT OR UPDATE ON compta.factures
FOR EACH ROW
EXECUTE FUNCTION trg_factures_audit();
Point important : en PostgreSQL, un trigger appelle une fonction qui retourne souvent TRIGGER. Ce n'est pas exactement le même modèle mental qu'un trigger Oracle, même si l'intention métier est proche.
Oracle PL/SQL PostgreSQL PL/pgSQL ------------------------------ --------------------------------------------- DBMS_OUTPUT.PUT_LINE RAISE NOTICE Bloc DECLARE/BEGIN/EXCEPTION bloc DO $$ ... $$ ou fonction/procedure SELECT ... INTO SELECT ... INTO %TYPE / %ROWTYPE %TYPE / %ROWTYPE Procedure appelee directement CALL ma_procedure(...) Fonction dans package fonction schéma.nom(...) Package pas d'équivalent direct, souvent schéma + fonctions Trigger PL/SQL trigger + trigger function NO_DATA_FOUND exception équivalente selon le contexte SQLERRM SQLERRM
Le point clé pour un expert Oracle : vous ne retrouverez pas le concept de package de la même manière. En PostgreSQL, on organise plus souvent par schémas, conventions de nommage et groupes de fonctions.
Voir aussi le tutoriel Oracle PL/SQL, le tutoriel Oracle SQL, le tutoriel PostgreSQL SQL et le tutoriel PostgreSQL avancé et administration.