ROWNUM, LIMIT, FETCH FIRST n ROW(S) ONLY
Il est parfois intéressant de limiter le nombre de résultats retournés par le SGBD pour une requête particulière. Certes, il est toujours possible de demander le jeu de résultats complet puis de nafficher que les premiers résultats. Mais, si un ensemble fixé de résultats est requis et que lon se moque des autres résultats, autant faire le travail en amont.
Les utilisateurs dOracle utilisent souvent pour cela ROWNUM, une pseudo-colonne attribuant un numéro à chaque ligne du jeu de résultats. Ajouter rownum < 4 à votre clause WHERE permettra ainsi de ne renvoyer que 3 résultats.
ROWNUM est spécifique Oracle mais avec dautres SGBD, comme dailleurs PostgreSQL, vous utilisez parfois le mot clé LIMIT. Toutes ces syntaxes ne sont pas standard SQL. Pour revenir à ROWNUM, une mauvaise compréhension de son fonctionnement peut même entraîner un problème de résultats faux.
Je vais partir dun exemple que jai rencontré en production sur un site. Pour traiter une pile de dossiers une requête Oracle renvoyait LE dossier le plus urgent à traiter. Au départ il sagissait dun problème de performance (pourquoi ne traiter quun dossier à la fois ?) mais il y avait plus grave. Illustration avec un exemple simplifié :
Ouille ! Le résultat attendu était "4" et il a fallu utiliser une sous-requête pour lobtenir. Le tri est en effet opéré APRÈS lapplication du filtrage via le ROWNUM comme Tom Kyte lexplique de manière approfondie dans cet article. Malheureusement cétait la première syntaxe qui était utilisée en production. Le moteur retournait une ligne puis triait cette unique ligne. Les dossiers ouverts étaient tout de même traités, mais pas dans lordre souhaité.
Mais comment écrire cette requête en SQL alors ? La norme SQL-2008 donne la réponse : utilisez FETCH FIRST n ROW(S) ONLY. Illustration avec PostgreSQL qui respecte la norme sur ce point depuis la version 8.4 sortie en 2009 :
Le tour est joué, le résultat attendu est obtenu avec une syntaxe simple et standard que vous pouvez dailleurs utiliser aussi avec Oracle Database à partir de la version 12.1 ou Microsoft SQL Server à partir de la version 2012. Oubliez les ROWNUM et les LIMIT !