paginacion sql sql-server oracle

sql - paginacion oracle rownum



Paginación con Oracle y el servidor SQL y el método de paginación genérico (7)

Quiero implementar la 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)?


"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 nuevas filas (por lo que las diez vistas por el usuario ya no son las más recientes).

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

¿Desea que ese nuevo conjunto incluya aquellos tres que se han visto afectados desde el 8/9/10 hasta el 11/12/13? Si no, en Oracle puede seleccionar los datos tal como estaban a las 10:30

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

Aún 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


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

En Oracle está aquí

NUMERO DE FILA

Sí, acaba de verificar que ROW_NUMBER es la misma función en ambos.


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.

Quizás pueda encapsular estas diferencias con una función que tome una instrucción de SQL determinada y los números de la primera y la última fila y genere el SQL paginatd apropiado para el DBMS objetivo, es decir, algo como:

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

que regresarí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 con los que deberá lidiar.


Si el conjunto de datos esperado es enorme, recomendaría 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 ya sea usando 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 obtención de datos reales de la búsqueda.


No existe una forma uniforme de garantizar la búsqueda en varios productos RDBMS. Oracle te da Rownum, que puedes usar en where, cláusula como:

where rownum < 1000

SQL Server le otorga la función row_id () que se puede usar de manera similar al rownum de Oracle. Sin embargo, row_id () no está disponible antes de SQL Server 2005.


Como otros han sugerido, puedes 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

necesitas anidarlo así

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 para esto es que rownum se determina después de la cláusula where y antes de la orden por cláusula. Para ver lo que quiero decir, puedes consultar

select rownum,first_name from some_table order by first_name

y podrías obtener

4 Diane 2 Norm 3 Sam 1 Woody

Eso es porque Oracle evalúa la cláusula where (ninguna en este caso), luego asigna rownums y luego ordena los resultados por first_name. Debe anidar la consulta para que use el rownum asignado después de ordenar las filas.

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 publicación es, probablemente debería haber publicado esos enlaces ...


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: tu consulta con orden por

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

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