2009-01-28 17 views
7

Quiero implementar paginación en una vista de cuadrícula o en una tabla html que llenaré usando ajax. ¿Cómo debo escribir consultas para soportar paginación? Por ejemplo, si pagesize es 20 y cuando el usuario hace clic en la página 3, las filas entre 41 y 60 deben mostrarse en la tabla. Al principio puedo obtener todos los registros y ponerlos en el caché, pero creo que esta es la manera incorrecta. Porque los datos pueden ser muy grandes y los datos pueden cambiar de otras sesiones. Entonces, ¿cómo puedo implementar esto? ¿Hay alguna forma genérica (para todas las bases de datos)?Paginación con el servidor Oracle y sql y el método de paginación genérico

Respuesta

4

Desafortunadamente, los métodos para restringir el rango de filas devuelto por una consulta varían de un DBMS a otro: Oracle usa ROWNUM (vea la respuesta de ocdecio), pero ROWNUM no funcionará en SQL Server.

Tal vez se puede encapsular estas diferencias con una función que toma una determinada sentencia de SQL y los números de la primera y última fila y genera el SQL paginatd apropiado para el DBMS de destino - es decir, algo así como:

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

cual se devolvía

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

para Oracle y algo más para SQL Server.

Sin embargo, tenga en cuenta que la solución Oracle está agregando una nueva columna RN a los resultados que deberá tratar.

1

Creo que ambos tienen una función analítica ROWNUM. Usa eso y serás idéntico.

En Oracle es here

ROW_NUMBER

Sí, simplemente verifica que ROW_NUMBER es la misma función en ambos.

0

Si el conjunto de datos esperado es enorme, recomiendo crear una tabla temporal, una vista o una instantánea (vista materializada) para almacenar los resultados de la consulta + un número de fila recuperado utilizando la función analítica ROWNUM o ROW_NUMBER. Después de eso, puede consultar este almacenamiento temporal utilizando los rangos de número de fila. Básicamente, debe separar la captación de datos reales de la paginación.

1

"Porque ... los datos pueden cambiar de otras sesiones". ¿Qué quieres que pase por esto?

Por ejemplo, el usuario obtiene las 'últimas' diez filas a las 10:30.

A las 10:31, se agregan 3 filas nuevas (por lo que las diez vistas por el usuario ya no son las más recientes).

A las 10:32, el usuario solicita entonces las 'siguientes' diez entradas.

¿Desea que ese nuevo conjunto incluya aquellos tres que se han desplazado del 8/9/10 al 11/12/13? Si no es así, en Oracle puede seleccionar los datos a medida que estaba en 10:30

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

Usted todavía necesita la lógica row_number, por ejemplo

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 
+0

La otra alternativa es en realidad tomar 100 filas al principio, pero solo mostrar 10 a la vez. El javascript solo tiene que ocultar/revelar las filas de la tabla. Esto cuenta con que los usuarios nunca deseen bajar la página más de diez veces. –

0

No hay manera uniforme para asegurar la paginación a través de varios Productos RDBMS.Oracle le da ROWNUM que se puede utilizar en la cláusula WHERE como:

where rownum < 1000 

SQL Server le da row_id() la función que se puede utilizar similar a rownum de Oracle. Sin embargo, row_id() no está disponible antes de SQL Server 2005.

17

Como han sugerido otros, puede usar rownum en Oracle. Aunque es un poco complicado y tienes que anidar tu consulta dos veces.

Por ejemplo, para paginar la consulta

select first_name from some_table order by first_name 

que necesita para anidar como este

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 razón de esto es que rownum se determina después la cláusula dónde y antes la orden por la cláusula. Para ver lo que quiero decir, puede consultar

select rownum,first_name from some_table order by first_name 

y puede obtener

4 Diane 
2 Norm 
3 Sam 
1 Woody 

Esto se debe a Oracle evalúa la cláusula where (ninguno en este caso), a continuación, asigna rownums, a continuación, ordena los resultados por nombre de pila. Debe anidar la consulta para que use el rownum asignado después de las filas se han ordenado.

La segunda anidación tiene que ver con cómo rownum se trata en una condición where. Básicamente, si consulta "where rownum> 100", no obtendrá ningún resultado. Es una cosa de gallina y huevo en la que no puede devolver ninguna fila hasta que encuentra rownum> 100, pero como no devuelve ninguna fila, nunca incrementa rownum, por lo que nunca cuenta hasta 100. Ugh. El segundo nivel de anidamiento resuelve esto. Tenga en cuenta que debe alias la columna Rownum en este punto.

Por último, su orden por cláusula debe hacer que la consulta sea determinista. Por ejemplo, si tiene John Doe y John Smith, y ordena por nombre solamente, entonces los dos pueden cambiar lugares de una ejecución de la consulta a la siguiente.

Hay artículos aquí http://www.oracle.com/technology/oramag/oracle/06-sep/o56asktom.html y aquí http://www.oracle.com/technology/oramag/oracle/07-jan/o17asktom.html. Ahora que veo cuánto tiempo mi mensaje es, probablemente debería tener acaba de publicar los enlaces ...

1
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; 

Paso 1: consulta con el fin de

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

Paso 3 : select * from () where rnum >= :MIN_ROW_TO_FETCH; poner 1 en 2 y 2 en 3