
Un curseur PL/SQL est un pointeur vers le résultat d’une requête, qui permet de parcourir les lignes une à une. Oracle en distingue deux types — implicites (gérés automatiquement) et explicites (que vous déclarez et contrôlez) — plus la boucle FOR qui simplifie tout. Ce guide complet couvre la syntaxe, les attributs et les bonnes pratiques, avec des exemples concrets.
🧪 Envie de pratiquer ? Exécutez les exemples de cet article dans notre SQL Playground gratuit — aucun logiciel à installer.
Curseur implicite vs explicite
- Implicite : créé automatiquement par Oracle pour chaque
SELECT INTO,INSERT,UPDATE,DELETE. Vous ne le déclarez pas, mais vous pouvez lire ses attributs (SQL%ROWCOUNT…). - Explicite : vous le déclarez pour traiter une requête qui ramène plusieurs lignes, avec un contrôle total (OPEN/FETCH/CLOSE).
Le curseur implicite
BEGIN
UPDATE comptes SET solde = solde * 1.01 WHERE actif = 'O';
DBMS_OUTPUT.put_line('Lignes mises à jour : ' || SQL%ROWCOUNT);
END;Attributs disponibles : SQL%FOUND, SQL%NOTFOUND, SQL%ROWCOUNT, SQL%ISOPEN (toujours FALSE pour l’implicite).
Le curseur explicite : OPEN / FETCH / CLOSE
DECLARE
CURSOR c_clients IS
SELECT id, nom FROM clients WHERE ville = 'Paris';
v_id clients.id%TYPE;
v_nom clients.nom%TYPE;
BEGIN
OPEN c_clients;
LOOP
FETCH c_clients INTO v_id, v_nom;
EXIT WHEN c_clients%NOTFOUND;
DBMS_OUTPUT.put_line(v_id || ' - ' || v_nom);
END LOOP;
CLOSE c_clients;
END;Les attributs s’utilisent avec le nom du curseur : c_clients%FOUND, %NOTFOUND, %ROWCOUNT, %ISOPEN. Pensez à toujours fermer le curseur (sinon fuite de ressources).
La boucle FOR : la méthode recommandée
Elle ouvre, parcourt et ferme le curseur automatiquement — moins de code, moins d’erreurs :
BEGIN
FOR r IN (SELECT id, nom FROM clients WHERE ville = 'Paris') LOOP
DBMS_OUTPUT.put_line(r.id || ' - ' || r.nom);
END LOOP;
END;Plus besoin de déclarer les variables ni de gérer OPEN/FETCH/CLOSE. Préférez cette forme dans 90% des cas.
Curseur paramétré
DECLARE
CURSOR c_par_ville(p_ville VARCHAR2) IS
SELECT nom FROM clients WHERE ville = p_ville;
BEGIN
FOR r IN c_par_ville('Lyon') LOOP
DBMS_OUTPUT.put_line(r.nom);
END LOOP;
END;Curseur avec FOR UPDATE (verrouillage)
Pour modifier les lignes parcourues en toute sécurité :
DECLARE
CURSOR c IS SELECT id, solde FROM comptes WHERE actif='O' FOR UPDATE;
BEGIN
FOR r IN c LOOP
UPDATE comptes SET solde = r.solde * 1.01 WHERE CURRENT OF c;
END LOOP;
COMMIT;
END;WHERE CURRENT OF c cible exactement la ligne en cours. Pour aller plus loin sur les verrous, voir notre tutoriel sur la gestion des transactions.
Bonnes pratiques & performances
- Évitez le « row-by-row » quand un seul ordre SQL suffit : un
UPDATE … WHEREensembliste est bien plus rapide qu’une boucle curseur. - Pour traiter de gros volumes ligne à ligne, utilisez BULK COLLECT et FORALL au lieu d’un FETCH unitaire.
- Ancrez les variables sur les colonnes avec
%TYPE/%ROWTYPEpour éviter ORA-06502. - Fermez toujours les curseurs explicites (la boucle FOR le fait pour vous).
FAQ
Quelle différence entre un curseur implicite et explicite ?
L’implicite est créé et géré par Oracle pour chaque ordre SQL ; l’explicite est déclaré et contrôlé par vous, pour parcourir plusieurs lignes.
Faut-il toujours fermer un curseur ?
Oui pour un curseur explicite ouvert avec OPEN. La boucle FOR IN s’en charge automatiquement.
Curseur ou requête ensembliste ?
Privilégiez toujours un ordre SQL unique (ensembliste) quand c’est possible : c’est plus rapide. Le curseur sert quand la logique ligne à ligne est inévitable.
