
FETCH FIRST en Oracle SQL : limiter le nombre de lignes retournées
La clause FETCH FIRST est une fonctionnalité introduite dans Oracle 12c qui permet de limiter facilement le nombre de lignes retournées par une requête SQL. Disponible depuis Oracle Database 12.1, elle remplace avantageusement les anciennes techniques basées sur ROWNUM. Que vous construisiez des classements, des tops produits ou une pagination, FETCH FIRST simplifie l’écriture de vos requêtes tout en améliorant leur lisibilité.
Définition et utilisation de FETCH FIRST
La clause FETCH FIRST fait partie de la syntaxe de limitation de lignes (Row Limiting Clause) introduite dans le standard SQL:2008 et implémentée dans Oracle 12c. Elle s’utilise en combinaison avec la clause ORDER BY pour sélectionner un nombre précis de lignes en haut d’un jeu de résultats trié.
Pourquoi utiliser FETCH FIRST plutôt que ROWNUM ?
Avant Oracle 12c, la méthode classique pour limiter les résultats était d’utiliser ROWNUM dans une sous-requête, ce qui rendait le code verbeux et sujet à des erreurs subtiles. La clause FETCH FIRST offre une syntaxe plus claire, plus proche du langage naturel, et s’intègre directement dans la requête principale sans nécessiter d’imbrication.
Cas d’usage en entreprise
- Top N produits : afficher les 10 articles les plus vendus d’un catalogue e-commerce.
- Classements RH : récupérer les 5 employés avec les salaires les plus élevés.
- Pagination : afficher la première page de résultats dans une interface utilisateur.
- Monitoring : isoler les N dernières erreurs dans un journal d’événements.
- Rapports financiers : extraire les 20 clients avec le chiffre d’affaires le plus important.
Syntaxe complète de FETCH FIRST
La syntaxe officielle de la clause de limitation de lignes avec FETCH FIRST en Oracle est la suivante :
SELECT colonnes
FROM table
[WHERE conditions]
[ORDER BY colonne [ASC | DESC]]
[OFFSET n ROWS]
FETCH { FIRST | NEXT } { n [PERCENT] } ROWS { ONLY | WITH TIES };
Explication des paramètres
| Paramètre | Description |
|---|---|
FETCH FIRST | Indique que l’on souhaite récupérer les premières lignes du résultat trié. |
FETCH NEXT | Synonyme de FETCH FIRST, utilisé pour la lisibilité avec OFFSET. |
n | Le nombre de lignes (ou le pourcentage) à retourner. |
PERCENT | Si présent, n représente un pourcentage du total des lignes. |
ROWS ONLY | Retourne exactement n lignes, sans exception. |
ROWS WITH TIES | Retourne n lignes minimum, mais inclut les lignes ex-æquo sur le dernier rang. |
OFFSET n ROWS | Ignore les n premières lignes avant d’appliquer FETCH FIRST (pagination). |
Note importante : L’utilisation de FETCH FIRST sans ORDER BY est techniquement possible mais déconseillée, car l’ordre des lignes retournées serait indéterministe.
Exemples pratiques de FETCH FIRST en Oracle
Exemple 1 – Top 5 des employés les mieux payés
Contexte métier : Un responsable RH souhaite obtenir la liste des 5 employés percevant les salaires les plus élevés dans la table EMPLOYEES (schéma HR d’Oracle).
-- Sélection des 5 employés avec les salaires les plus élevés
SELECT
employee_id,
first_name || ' ' || last_name AS nom_complet,
salary,
department_id
FROM employees
ORDER BY salary DESC
FETCH FIRST 5 ROWS ONLY;
Résultat attendu : Les 5 lignes correspondant aux salaires les plus élevés, triées de manière décroissante. La clause ONLY garantit qu’exactement 5 lignes sont retournées, même si plusieurs employés ont le même salaire que le 5e.
Exemple 2 – Pagination avec OFFSET et FETCH FIRST
Contexte métier : Une application e-commerce affiche un catalogue de produits par pages de 10 articles. Pour afficher la 3e page, il faut ignorer les 20 premiers résultats et récupérer les 10 suivants.
-- Affichage de la 3e page d'un catalogue produits (10 articles par page)
-- Page 1 : OFFSET 0, Page 2 : OFFSET 10, Page 3 : OFFSET 20
SELECT
product_id,
product_name,
list_price,
category_id
FROM products
ORDER BY list_price ASC, product_id ASC
OFFSET 20 ROWS -- On ignore les 20 premiers résultats
FETCH NEXT 10 ROWS ONLY; -- On récupère les 10 lignes suivantes
Explication : L’utilisation de FETCH NEXT à la place de FETCH FIRST est ici purement stylistique, mais améliore la lisibilité en indiquant clairement que l’on prend les lignes « suivantes » après l’offset. Le double critère de tri (list_price puis product_id) assure un ordre stable entre les pages.
Exemple bonus – Utilisation de WITH TIES
Contexte métier : On souhaite afficher les 3 meilleurs clients par chiffre d’affaires, en incluant tous les clients ex-æquo sur la 3e place.
-- Top 3 clients avec gestion des ex-æquo
SELECT
client_id,
client_name,
chiffre_affaires
FROM clients
ORDER BY chiffre_affaires DESC
FETCH FIRST 3 ROWS WITH TIES;
Si deux clients partagent le 3e rang, la requête retournera 4 lignes (ou plus) au lieu de 3. C’est le comportement attendu avec WITH TIES.
Erreurs courantes avec FETCH FIRST
Erreur : utiliser FETCH FIRST sans ORDER BY sur une colonne stable
Problème : De nombreux développeurs utilisent FETCH FIRST sans clause ORDER BY, ou avec un ordre non déterministe (ex : tri sur une colonne contenant des doublons sans discriminant secondaire). Cela peut produire des résultats incohérents d’une exécution à l’autre, notamment lors d’une pagination.
-- ❌ Requête incorrecte : tri non stable, résultats imprévisibles entre pages
SELECT product_id, product_name
FROM products
ORDER BY category_id -- Plusieurs produits peuvent avoir le même category_id
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY;
-- ✅ Requête correcte : ajout d'un discriminant unique pour garantir l'ordre
SELECT product_id, product_name
FROM products
ORDER BY category_id, product_id -- product_id est unique = ordre garanti
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY;
Solution : Ajoutez toujours une colonne unique (comme une clé primaire) comme critère de tri secondaire pour garantir un ordre stable et des pages de résultats cohérentes.
Note de compatibilité : La clause FETCH FIRST n’est disponible qu’à partir d’Oracle Database 12c (12.1). Sur les versions antérieures, il faut utiliser ROWNUM ou la fonction analytique ROW_NUMBER().
Résumé
Tableau récapitulatif des points clés
| Point clé | Détail |
|---|---|
| Disponibilité | Oracle Database 12c (12.1) et versions supérieures |
| Objectif principal | Limiter le nombre de lignes retournées par une requête |
ROWS ONLY | Retourne exactement N lignes |
ROWS WITH TIES | Inclut les lignes ex-æquo sur le dernier rang |
PERCENT | Limite en pourcentage du total de lignes |
OFFSET | Saute les N premières lignes (pagination) |
| Alternative ancienne | ROWNUM ou ROW_NUMBER() pour Oracle < 12c |
2 bonnes pratiques Oracle
- Toujours associer FETCH FIRST à un ORDER BY déterministe : utilisez systématiquement une colonne unique (clé primaire) comme critère de tri secondaire pour garantir des résultats reproductibles, surtout dans un contexte de pagination.
- Préférer FETCH FIRST à ROWNUM pour Oracle 12c+ : la clause de limitation de lignes est plus lisible, plus maintenable et moins sujette aux erreurs de sous-requête que l’ancienne méthode
WHERE ROWNUM <= n. Elle exprime clairement l’intention du développeur.
Aller plus loin
Pour approfondir vos connaissances sur la gestion des résultats et le classement en Oracle SQL, découvrez ces sujets complémentaires :
- ROWNUM en Oracle : l’ancienne méthode pour limiter les lignes — Comprendre les différences entre
ROWNUMetFETCH FIRSTet savoir quand utiliser l’une ou l’autre technique. - ROW_NUMBER() en Oracle : numéroter et paginer les résultats — Maîtriser la fonction analytique
ROW_NUMBER()pour des cas de pagination avancée et de classement conditionnel. - ORDER BY en Oracle SQL : trier vos données efficacement — Tout savoir sur le tri des résultats, les ordres croissants/décroissants et la gestion des valeurs NULL avec
NULLS FIRST / NULLS LAST.
Sur le même thème
- SELECT en SQL Oracle : syntaxe et exemples pratiques
- UPDATE en SQL Oracle : modifier des données facilement
- INSERT en SQL Oracle : syntaxe, exemples et bonnes pratiques
- MERGE Oracle SQL : Syntaxe, Exemples et Bonnes Pratiques
- ORDER BY en SQL Oracle : tri des résultats expliqué
- ROLLBACK Oracle : annuler une transaction SQL facilement
