2008-09-15 8 views
7

Tâche: implémenter la pagination d'enregistrements de base de données adaptés à différents SGBDR. La méthode devrait fonctionner pour les moteurs traditionnels - MSSQL2000 +, Oracle, MySql, etc.Comment implémenter la pagination indépendante du moteur de base de données?

Veuillez ne pas publier de solutions spécifiques au SGBDR, je sais comment implémenter cela pour la plupart des moteurs de base de données modernes. Je cherche la solution universelle. Seules les solutions basées sur des tables temporaires me viennent à l'esprit pour le moment.

EDIT:
Je cherche une solution SQL, pas la bibliothèque 3ème partie.

Répondre

5

Il y aurait eu une solution universelle si les spécifications SQL avaient inclus la pagination en tant que norme. L'exigence que n'importe quel langage de SGBDR soit appelé langage de SGBDR n'inclut pas non plus le support de pagination.

De nombreux produits de base de données prennent en charge SQL avec des extensions propriétaires de la langue standard. Certains d'entre eux supportent la pagination comme MySQL avec la clause limit, Rowid avec Oracle; chacun géré différemment. D'autres SGBD devront ajouter un champ appelé rowid ou quelque chose comme ça. Je ne pense pas que vous puissiez avoir une solution universelle (n'importe qui est libre de me donner tort ici, ouvert au débat) à moins qu'il ne soit intégré dans le système de base de données lui-même ou à moins qu'il y ait une entreprise qui utilise Oracle, MySQL, SQL Server et ils décident d'avoir tous les différents systèmes de base de données fournissent leur propre mise en œuvre de la pagination par leurs développeurs de base de données fournissant une interface universelle pour le code qui l'utilise.

+0

Oui, j'ai essayé différentes solutions, mais il semble impossible de créer une version plus ou moins portable. – aku

0

JPA vous permet de le faire avec la classe de requête:

Query q = ...; 
q.setFirstResult (0); 
q.setMaxResults (10); 

vous donne les 10 premiers résultats dans le jeu de résultats.

Si vous voulez une solution SQL brute indépendante du SGBD, je crains que vous n'ayez pas de chance. Tous les vendeurs le font différemment.

3

La manière la plus naturelle et la plus efficace de faire du paging est d'utiliser la construction LIMIT/OFFSET (TOP dans le monde Sybase). Un DBindependent devrait savoir sur quel moteur il s'exécute et appliquer la construction SQL appropriée. Au moins, c'est comme cela que je l'ai vu dans le code des bibliothèques indépendantes DB. Vous pouvez faire abstraction de la logique de pagination une fois que vous avez obtenu les données du moteur avec la requête spécifique.

Si vous êtes vraiment à la recherche d'une seule solution SQL, pourriez-vous montrer ce que vous avez en tête? Comme le SQL pour la solution de table temporaire. Cela vous donnerait probablement des suggestions plus pertinentes.

EDIT:

Je voulais voir à quoi tu pensais parce que je ne pouvais pas voir une façon de le faire avec des tables temporaires et ne pas utiliser un moteur construction spécifique. Vous avez utilisé des constructions spécifiques dans l'exemple. Je ne vois toujours pas un moyen d'implémenter la pagination dans la base de données avec seulement du SQL standard (implémenté). Vous pourriez apporter toute la table en SQL standard et la page dans l'application, mais c'est évidemment stupide. Donc, la question serait maintenant plus comme "Y at-il un moyen d'implémenter la pagination sans utiliser LIMIT/OFFSET ou équivalent?" et je suppose que la réponse est "Sanely, non". Vous pouvez essayer d'utiliser des curseurs, mais vous risquez également de tomber dans des phrases/comportements spécifiques à la base de données. Une idée wacko (stupide de lecture) que je viens de me voir serait d'ajouter une colonne de page à la table, par exemple créer un test de table (ID int, nom varchar, téléphone varchar, page int) et vous pouvez obtenir la page 1 avec select * from table où page = 1. Mais cela signifie que vous devez ajouter du code pour maintenir cette colonne, ce qui, encore une fois, ne peut être fait qu'en amenant toute la base de données ou en utilisant des constructions spécifiques. Cela en plus d'avoir à ajouter une colonne différente pour chaque ordre possible et de nombreux autres défauts.

Je ne peux pas fournir de preuve, mais je pense vraiment que vous ne pouvez pas le faire sainement.

1

Procédez comme d'habitude:
Commencez par l'implémenter conformément à la norme. Et puis gérer les cas de coin, c'est-à-dire les DBMS qui n'implémentent pas la norme. Comment gérer les cas de coin dépend de votre environnement de développement.

Vous recherchez une approche "universelle". La façon la plus universelle de paginer est l'utilisation de curseurs, mais la pagination basée sur le curseur ne correspond pas très bien à un environnement sans état, comme une application Web.

J'ai écrit sur la norme et les mises en œuvre (y compris les curseurs) ici: http://troels.arvin.dk/db/rdbms/#select-limit-offset

+0

Troels Arvin, page très utile, merci! – aku

0

@Vinko Vrsalovic,

comme je l'ai écrit en question, je sais comment le faire dans la plupart des blocs de données. Je trouve quoi trouver une solution universelle ou obtenir une preuve qu'elle n'existe pas.

Voici une solution stupide basée sur une table temporaire. C'est évidemment mauvais, donc pas besoin de commenter.

N - upper bound 
M - lower bound 

create #temp (Id int identity, originalId int) 

insert into #temp(originalId) 
select top N KeyColumn from MyTable 
where ... 

select MyTable.* from MyTable 
join #temp t on t.originalId = MyTable.KeyColumn 
where Id between M and M 
order by Id asc 

drop #temp 
+0

Le problème avec cette approche est que même si IDENTITY est un langage SQL standard, il n'est pas disponible dans toutes les bases de données. En outre, SELECT TOP n'est ni un SQL standard, ni largement implémenté. En dehors de cela, la copie de données peut être une opération beaucoup plus lente par rapport aux méthodes qui n'utilisent pas une table temporaire. –

+0

Peut-être qu'une vue pourrait être appliquée plutôt que de créer une table temporaire? Pouvez-vous créer une vue où l'une des colonnes est une colonne d'identité? –

+0

@ 1800 INFORMATIONS, pouvez-vous montrer un exemple – aku

Questions connexes