Pour gérer la pagination de données avec MySQL, on peut écrire ceci :
select * from t order by id limit 0, 20; -- démarre à 0 et lit 20 lignes
select * from t order by id limit 20, 20; -- lit 20 lignes à partir de la ligne 20
Sur DB2 (dont DB2/400 à partir de la V5R4), on pourra obtenir le même résultat grâce à la clause OVER. Démonstration ci-dessous (avec 2 variantes de la même solution) :
Soit la table ENT_LOG (entités logiques) créée dans la base TSTDATAB avec la structure suivante :
connect to tstdatab;
create table tstdatab.ent_log (
entl_app char(10) not null with default,
entl_id integer not null with default,
entl_nom char (20 ) not null with default,
entl_des char (50 ) not null with default,
) ;
connect reset;
La requête de pagination sera la suivante (affichage des lignes n° 10 à 20)Â :
1ère solution : sans la clause WITH
select * from (
select entl_id, entl_nom, entl_des,
row_number() over (order by entl_nom asc) as rn
from tstdatab.ent_log
) as foo
where rn between 10 and 20 ;
2ème solution : avec utilisation de la clause WITH
with devshedtest as
( select entl_id, entl_nom, entl_des,
row_number() over (order by entl_nom asc) as rn
from tstdatab.ent_log )
select entl_id, entl_nom, entl_des, rn
from devshedtest
where rn between 10 and 20 ;
J’ai testé ces 2 techniques avec une table contenant environ 3500 lignes. Elles donnent le même résultat avec des temps d’exécution identiques (inférieur à la seconde sur DB2 en version 9 sous Windows).
Piège à éviter : sur DB2/400 en V5R3, la clause OVER ne fonctionnant pas, on pourrait être tenté de gérer la pagination via la technique suivante (qui ne fonctionne pas) :
select * from
(
select a.*, rrn(a) as rn from lstpays a
) as foo
where rn between 1 and 10
order by codfra
En effet, cette technique ne peut pas fonctionner, car la fonction RRN() renvoie le numéro relatif de ligne, qui ne correspond en aucun cas au numéro de la ligne à l’intérieur du «  result set » obtenu.
La solution à ce problème, que j’ai trouvée sur un forum dédié à DB2 pour Z/OS, est la suivante :
select *
from lstpays a,
table (
select count(*) as rownum
from lstpays as b
where a.codfra >= b.codfra
) temp_tab
Where rownum between 11 and 20
order by rownum, codfra
fetch first 10 rows only