Pagination avec server Oracle et SQL et méthode de pagination générique

Je veux mettre en application la pagination dans un gridview ou dans une table html que je remplirai en utilisant ajax. Comment écrire des requêtes pour prendre en charge la pagination? Par exemple, si la taille de la page est de 20 et que l'user clique sur la page 3, les lignes entre 41 et 60 doivent être affichées sur la table. Au début, je peux get tous les loggings et les mettre en cache, mais je pense que c'est la mauvaise façon. Parce que datatables peuvent être très importantes et datatables peuvent être modifiées à partir d'autres sessions. alors comment puis-je mettre en œuvre cela? Y a-t-il un moyen générique (pour toutes les bases de données)?

Comme d'autres l'ont suggéré, vous pouvez utiliser rownum dans Oracle. C'est un peu difficile et vous devez imbriquer votre requête deux fois.

Par exemple, pour paginer la requête

select first_name from some_table order by first_name 

vous devez l'imbriquer comme ça

 select first_name from (select rownum as rn, first_name from (select first_name from some_table order by first_name) ) where rn > 100 and rn <= 200 

La raison en est que rownum est déterminé après la clause where et avant la clause order by. Pour voir ce que je veux dire, vous pouvez interroger

 select rownum,first_name from some_table order by first_name 

et vous pourriez get

 4 Diane 2 Norm 3 Sam 1 Woody 

En effet, oracle évalue la clause where (aucune dans ce cas), puis assigne rownums, puis sortinge les résultats par first_name. Vous devez imbriquer la requête afin qu'elle utilise la rownum assignée après le sorting des lignes.

La deuxième imbrication concerne la façon dont le rownum est traité dans un état où. Fondamentalement, si vous interrogez "where rownum> 100" alors vous n'obtenez aucun résultat. C'est un poulet et un oeuf où il ne peut returnner aucune ligne jusqu'à ce qu'il trouve rownum> 100, mais comme il ne returnne aucune ligne il n'augmente jamais rownum, donc il ne count jamais jusqu'à 100. Ugh. Le deuxième niveau d'imbrication résout ceci. Notez qu'il doit alias la colonne rownum à ce stade.

Enfin, votre clause order by doit rendre la requête déterministe. Par exemple, si vous avez John Doe et John Smith, et vous commandz par prénom seulement, alors les deux peuvent passer d'une exécution de la requête à l'autre.

Il y a des articles ici http://www.oracle.com/technology/oramag/oracle/06-sep/o56asktom.html et ici http://www.oracle.com/technology/oramag/oracle/07-jan/o17asktom .html . Maintenant que je vois combien de time mon post est, je devrais probablement juste posté ces liens …

Malheureusement, les methods pour restreindre la plage de lignes renvoyées par une requête varient d'un SGBD à l'autre: Oracle utilise ROWNUM (voir la réponse d'ocdecio), mais ROWNUM ne fonctionnera pas dans SQL Server.

Vous pouvez peut-être encapsuler ces différences avec une fonction qui prend une instruction SQL donnée et des numéros de première et dernière lignes et génère le code SQL paginatd approprié pour le SGBD cible, c'est-à-dire quelque chose comme:

 sql = paginated ('select empno, ename from emp where job = ?', 101, 150) 

qui reviendrait

 'select * from (select v.*, ROWNUM rn from (' + theSql + ') v where rownum < 150) where rn >= 101' 

pour Oracle et quelque chose d'autre pour SQL Server.

Toutefois, notez que la solution Oracle ajoute une nouvelle colonne RN aux résultats dont vous aurez besoin.

Je crois que les deux ont une fonction analytique ROWNUM. Utilisez cela et vous serez identique.

Dans Oracle, c'est ici

ROW_NUMBER

Oui, juste vérifié que ROW_NUMBER est la même fonction dans les deux.

"Parce que … datatables peuvent changer d'autres sessions." Que veux-tu arriver pour ça?

Par exemple, l'user obtient les dix dernières lignes à 10h30.

A 10:31, 3 nouvelles lignes sont ajoutées (donc les dix vues de l'user ne sont plus les dernières).

A 10h32, l'user request alors 'ensuite' dix inputs.

Voulez-vous que ce nouvel set inclue les trois qui ont été supprimés du 8/9/10 au 11/12/13? Sinon, dans Oracle, vous pouvez sélectionner datatables telles qu'elles étaient à 10h30

 SELECT * FROM table_1 as of timestamp (timestamp '2009-01-29 10:30:00'); 

Vous avez toujours besoin de la logique row_number, par exemple

  select * from (SELECT a.*, row_number() over (order by hire_date) rn FROM hr.employees as of timestamp (timestamp '2009-01-29 10:30:00') a) where rn between 10 and 19 
 select * from ( select /*+ FIRST_ROWS(n) */ a.*, ROWNUM rnum from ( your_query_goes_here, with order by ) a where ROWNUM <= :MAX_ROW_TO_FETCH ) where rnum >= :MIN_ROW_TO_FETCH; 

Étape 1: votre requête avec command par

Étape 2: select a.*, ROWNUM rnum from ()a where ROWNUM <=:MAX_ROW_TO_FETCH

Étape 3: select * from ( ) where rnum >= :MIN_ROW_TO_FETCH; mettre 1 sur 2 et 2 sur 3

Si l'set de données attendu est énorme, je vous recommand de créer une table temporaire, une vue ou un instantané (vue matérialisée) pour stocker les résultats de la requête + un numéro de ligne récupéré à l'aide de la fonction analytique ROWNUM ou ROW_NUMBER. Après cela, vous pouvez simplement interroger ce stockage temporaire en utilisant des plages de numéros de lignes. Fondamentalement, vous devez séparer l'extraction de données réelles de la pagination.

Il n'y a pas de moyen uniforme d'assurer la radiomessagerie à travers différents produits SGBDR. Oracle vous donne rownum que vous pouvez utiliser dans where clause comme:

 where rownum < 1000 

SQL Server vous donne la fonction row_id () qui peut être utilisée similaire au rownum d'Oracle. Toutefois, row_id () n'est pas disponible avant SQL Server 2005.