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