[ORACLE] PL/SQL Affichage par page.

PL/SQL Affichage par page. [ORACLE] - SQL/NoSQL - Programmation

Marsh Posté le 04-02-2003 à 17:43:40    

-- Pour avoir le nombre d'enregistrement.
 
SELECT COUNT(*)
FROM
 CptMouvement,
 CptTransaction
WHERE
 CptMouvement.COMPTE_ROBID = 6180
 AND CptTransaction.robId = CptMouvement.TRANSACTIONFIN_ROBID
 AND CptTransaction.dateCreation < ( SYSDATE + 1 )
 AND CptTransaction.dateCreation > ADD_MONTHS( SYSDATE + 1, -1 );
 
 
-- Pour avoir la troisième page de 10 enregistrements.
 
SELECT
 *
FROM (
 SELECT
  ROWNUM x, a, b, c
 FROM (
   SELECT
    CptTransaction.dateCreation a,
    CptMouvement.Robid b,
    CptMouvement.montant c
   FROM
    CptMouvement,
    CptTransaction
   WHERE
    CptMouvement.COMPTE_ROBID = 6180
    AND CptTransaction.robId = CptMouvement.TRANSACTIONFIN_ROBID
    AND CptTransaction.dateCreation < ( SYSDATE + 1 )
    AND CptTransaction.dateCreation > ADD_MONTHS( SYSDATE + 1, -1 )
   ORDER BY
    CptTransaction.dateCreation DESC
  )
 )
WHERE
 x >= 21
 AND x <= 30;
 
 
 
-----------------------------------------------------------------------------------------
 
 
Bonjour les gens  :jap:  
 
J'ai un peu cherché, et à force de ne pas trouver, j'ai inventé...
 
Quoi ? Ben un affichage par page pour les requêtes sous ORACLE.
 
Pour avoir 10 enregistrements à partir du 11ème, en MySql, c'est simple :
 

Code :
  1. SELECT * FROM MaTable WHERE Blabla... ORDER BY... LIMIT 10 rows 10


 
Avec Oracle, çà l'est Beaucoup MOINS !
 
Y'a bien une notion de ROWNUM, mais elle n'est pas très pratique à utiliser :
 
1- Le ROWNUM n'est généré que pour les enregistrements réellement retourné. Le premier est donc toujours 1.
Si on fait un WHERE ROWNUM > 10 par exemple, la requête ne retourne rien. En revanche, on peut mettre une limite supérieure.
 
2- Le ROWNUM est généré AVANT le ORDER BY, ce qui fait que dans les cas d'un affichage par page, on a un problème :
exemple :
 
SELECT ROWNUM, MONTANT, DATE FROM VENTES ORDER BY MONTANT DESC;
 

Code :
  1. ROWNUM MONTANT DATE
  2. 7  200  2002/12/21
  3. 5  190  2002/12/10
  4. 3  175  2002/12/05
  5. 1  120  2002/12/03
  6. 2  75  2002/12/05
  7. 9  75  2002/12/28
  8. 6  50  2002/12/19
  9. 4  15  2002/12/07
  10. 8  10  2002/12/24


 
Si je limite ROWNUM à 5, (la première page) je voudrais avoir çà :
 

Code :
  1. 1  200  2002/12/21
  2. 2  190  2002/12/10
  3. 3  175  2002/12/05
  4. 4  120  2002/12/03
  5. 5  75  2002/12/05


 
Mais en fait j'aurais çà :
 

Code :
  1. 5  190  2002/12/10
  2. 3  175  2002/12/05
  3. 1  120  2002/12/03
  4. 2  75  2002/12/05
  5. 4  15  2002/12/07


 
Il faut donc trouver une solution pour les deux problèmes.
 
J'ai pas trouvé mieux que ce qui suit pour avoir, par exemple, la deuxième page ( par page de 10 ):
 

Code :
  1. SELECT
  2. *
  3. FROM (
  4. SELECT
  5.  ROWNUM x, MONTANT, DATE
  6. FROM (
  7.  SELECT
  8.   MONTANT,
  9.   DATE
  10.  FROM
  11.   VENTES
  12.  WHERE
  13.   CAT=1
  14.  ORDER BY MONTANT DESC
  15.  )
  16. )
  17. WHERE
  18. x >= 21
  19. AND x <= 30;


   
Ce qui fait quand même 3 requêtes imbriquées au minimum !
 
Ce que j'aimerai savoir, c'est si je me suis cassé la tête pour rien, ou si y'a pas de meilleur solution...
   
   


Message édité par Mara's dad le 04-02-2003 à 17:46:10

---------------
Laissez l'Etat dans les toilettes où vous l'avez trouvé.
Reply

Marsh Posté le 04-02-2003 à 17:43:40   

Reply

Marsh Posté le 05-02-2003 à 12:21:31    

C'est sûr que c'est difficile de manipuler des enregistrements triés avec rownum.
 
Mais es-tu obligé de faire cela par le SQL ? Dans le principe, on renvoie le jeu d'enregistrements à l'application cliente, charge à elle de les présenter comme elle l'entend.
Si c'est pour imprimer directement à partir de SqlPlus, utilise de préférence les commandes de mises en page qui sont assez puissantes (par exemple, SET PAGESIZE x pour x enregistrements par page).
Dans des procédures stockées, tu peux utiliser les curseurs pour controler facilement des paquets enregistrements. C'est ce que je fais pour parallèliser des traitements sur des grosses tranches d'enregistrements sans chevauchement.
J'ai pas de solution meilleure que la tienne. Pour des petits rapports vite fait, en général je m'arrange pour exporter le résultat complet vers un fichier que je retraite en fonction de son contenu.
 :hello:  

Reply

Marsh Posté le 05-02-2003 à 14:27:35    

En fait je code çà dans des prodédures stockées qui sont appelées par des appli minitel ou web.
 
Les applis donnent en entrée le numéro de page voulu avec le nombre de lignes par page, et la proc retourne des 'TABLE OF VARCHAR2' pour chaque champ, ainsi que le nombre de pages dispo suivant le nombre de ligne max.
 
Bien sûr au premier appel, le numéro de page doit être 1.
Evidement, le minitel et le WEB ne gèrent pas le même nombre de lignes par page.
 
Je ne peut pas me permettre d'envoyer la totalité des enregs aux applis à chaque fois...
 
D'autre part, faire un curseur, puis boucler dans le vide pour passer les premiers enregistrement est une hérésie complète par rapport à une requête comme celle que je fait. Même avec 3 requêtes imbriquée, le moteur SQL d'oracle encore beaucoup plus efficace qu'une boucle PL/SQL pour sauter les premier enregs. Surtout quand y'en a beaucoup beaucoup!
 
En tout cas merçi d'avoir fait remonter mon post  :)


---------------
Laissez l'Etat dans les toilettes où vous l'avez trouvé.
Reply

Marsh Posté le 05-02-2003 à 14:31:10    

J'avais pas bien lu :
 
"tu peux utiliser les curseurs pour controler facilement des paquets enregistrements"
 
Comment tu fais pour limiter l'action du cuseur sur une 'fenêtre' particulière ? ? ?


---------------
Laissez l'Etat dans les toilettes où vous l'avez trouvé.
Reply

Marsh Posté le 05-02-2003 à 14:38:03    

Mara's dad a écrit :

J'avais pas bien lu :
 
"tu peux utiliser les curseurs pour controler facilement des paquets enregistrements"
 
Comment tu fais pour limiter l'action du cuseur sur une 'fenêtre' particulière ? ? ?


Je pense que tu dois pouvoir utiliser des fonction sur les ROWID via le package DBMS_ROWID :

Citation :

Extended ROWIDs
The Oracle8 extended ROWID datatype stored in a user column includes the data in the restricted ROWID plus a data object number. The data object number is an identification number assigned to every database segment. You can retrieve the data object number from data dictionary views USER_OBJECTS, DBA_OBJECTS, and ALL_OBJECTS. Objects that share the same segment (clustered tables in the same cluster, for example) have the same object number.  
 
Extended ROWIDs are not available directly. You can use a supplied package, DBMS_ROWID, to interpret extended ROWID contents. The package functions extract and provide information that would be available directly from a restricted ROWID. You can use functions from the DBMS_ROWID package as you would any built-in SQL function. Table 2-2 lists the functions and procedures in the DBMS_ROWID package. For more information on DBMS_ROWID, see Oracle8 Application Developer's Guide.  
 


en particulier, tu as la fonction ROWID_ROWNUMBER qui te retourne le numéro de l'enregistrement.


---------------
Gérez votre collection de BD en ligne ! ---- Electro-jazzy song ---- Dazie Mae - jazzy/bluesy/cabaret et plus si affinité
Reply

Marsh Posté le 05-02-2003 à 15:18:53    

C'est gentil de pense à moi, mais les ROWID ne sont pas utilisables. Ils sont spécifiques à chaque table, et mes requêtes portent sur plusieurs tables ( Ce que je n'avais pas indiqué il est vrai :) ).
 
D'autre part la fonction ROWID_ROWNUMBER me retourne le numéro d'ordre de l'enregistrement dans une table. Moi, j'ai besoin d'un numéro d'ordre commançant à 1 pour ma requête et s'incrémentant de 1 en 1 à chaque ligne. C'est ce que fait le ROWNUM, à condition de le sortir pour qu'il prennent en compte la clause "ORDER BY".
 
Décidément, plus je cherche et plus je panse qu'il n'y a pas d'autre solution.


---------------
Laissez l'Etat dans les toilettes où vous l'avez trouvé.
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed