2009-01-28 13 views
7

Ich möchte Paging in einer Gridview oder in einer HTML-Tabelle implementieren, die ich mit Ajax füllen werde. Wie sollte ich Abfragen schreiben, um Paging zu unterstützen? Wenn beispielsweise die Seitengröße 20 ist und der Benutzer auf Seite 3 klickt, müssen Zeilen zwischen 41 und 60 in der Tabelle angezeigt werden. Zuerst kann ich alle Aufzeichnungen bekommen und sie in den Cache stellen, aber ich denke, das ist der falsche Weg. Weil Daten sehr groß sein können und Daten von anderen Sitzungen geändert werden können. Wie kann ich das umsetzen? Gibt es einen generischen Weg (für alle Datenbanken)?Paging mit Oracle und SQL-Server und generische Paging-Methode

Antwort

4

Leider variieren die Methoden zum Einschränken der Anzahl der von einer Abfrage zurückgegebenen Zeilen von einem DBMS zu einem anderen: Oracle verwendet ROWNUM (siehe ocdecios Antwort), aber ROWNUM funktioniert nicht in SQL Server.

Vielleicht können Sie diese Unterschiede mit einer Funktion kapseln, die eine bestimmte SQL-Anweisung und die erste und letzte Zeile Zahlen und erzeugt für die Ziel-DBMS die entsprechende paginatd SQL nimmt - also so etwas wie:

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

, die zurückkehren

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

für Oracle und etwas anderes für SQL Server.

Beachten Sie jedoch, dass die Oracle-Lösung eine neue Spalte RN zu den Ergebnissen hinzufügt, mit denen Sie arbeiten müssen.

1

Ich glaube, dass beide eine ROWNUM analytische Funktion haben. Benutze das und du wirst identisch sein.

In Oracle ist es here

ROW_NUMBER

Yep, nur bestätigt, dass ROW_NUMBER die gleiche Funktion in beiden ist.

0

Wenn der erwartete Datensatz sehr groß ist, würde ich empfehlen, eine temporäre Tabelle, eine Ansicht oder einen Snapshot (materialisierte Ansicht) zu erstellen, um die Abfrageergebnisse + eine Zeilennummer entweder mithilfe der ROWNUM- oder ROW_NUMBER-Analysefunktion zu speichern. Danach können Sie diesen temporären Speicher einfach über Zeilennummernbereiche abfragen. Grundsätzlich müssen Sie den tatsächlichen Datenabruf vom Paging trennen.

1

"Weil ... Daten von anderen Sitzungen geändert werden können." Was möchten Sie dafür tun?

Zum Beispiel erhält der Benutzer die "neuesten" zehn Zeilen um 10:30 Uhr.

Um 10:31 werden 3 neue Zeilen hinzugefügt (so dass die zehn vom Benutzer angezeigten nicht mehr die neuesten sind).

Um 10:32, fordert der Benutzer dann "nächste" zehn Einträge.

Möchten Sie, dass der neue Satz jene drei einschließt, die vom 09.08.10 bis zum 11.12.13 gestoßen wurden? Wenn nicht, in Oracle können Sie die Daten auswählen, wie es um 10:30 Uhr war

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

Sie müssen noch die row_number Logik, zB

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

die andere alternative tatsächlich zu Beginn 100 Zeilen wird greifen aber 10 nur zu einer Zeit zeigen. Das Javascript muss nur Tabellenzeilen verstecken/offen legen. Dies bedeutet, dass Benutzer nie mehr als zehn Mal blättern möchten. –

0

Es gibt keine einheitliche Weise Paging über verschiedene, um sicherzustellen, RDBMS-Produkte.Oracle gibt Ihnen rownum, die Sie in where-Klausel wie verwenden:

where rownum < 1000 

SQL Server gibt Ihnen row_id() Funktion, die auf Oracle rownum ähnlich verwendet werden kann. Row_id() ist jedoch nicht vor SQL Server 2005 verfügbar.

17

Wie andere vorgeschlagen haben, können Sie in Oracle rownum verwenden. Es ist ein wenig schwierig, und Sie müssen Ihre Abfrage zweimal verschachteln.

Zum Beispiel Paginieren die Abfrage

select first_name from some_table order by first_name 

Sie es wie dieser

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 

Der Grund dafür nisten müssen, ist, dass rownum nach bestimmt wird, die where-Klausel und vor die Reihenfolge nach Klausel. Um zu sehen, was ich meine, können Sie

select rownum,first_name from some_table order by first_name 

abfragen und Sie könnten

4 Diane 
2 Norm 
3 Sam 
1 Woody 

bekommen Das ist, weil Oracle die where-Klausel (keine in diesem Fall) auswertet, dann rownums ordnet, sortiert dann die Ergebnisse von Vorname. Sie müssen die Abfrage so verschachteln, dass sie das zugewiesene rownum verwendet, nachdem die Zeilen sortiert worden sind.

Die zweite Verschachtelung hat damit zu tun, wie das Rotwnum in einem bestimmten Zustand behandelt wird. Im Grunde genommen, wenn Sie "where rownum> 100" abfragen, erhalten Sie keine Ergebnisse. Es ist ein Huhn und Ei-Ding, wo es keine Reihen zurückgeben kann, bis es rownum> 100 findet, aber da es keine Reihen zurückgibt, erhöht es nie rownum, also zählt es nie zu 100. Ugh. Die zweite Verschachtelungsstufe löst dies. Beachten Sie, dass es an dieser Stelle die rownum-Spalte aliasieren muss.

Schließlich muss Ihre Order by-Klausel die Abfrage deterministisch machen. Wenn Sie beispielsweise John Doe und John Smith haben und nur nach dem Vornamen sortieren, können die beiden Orte von einer Ausführung der Abfrage zur nächsten wechseln.

Es gibt Artikel hier http://www.oracle.com/technology/oramag/oracle/06-sep/o56asktom.html und hier http://www.oracle.com/technology/oramag/oracle/07-jan/o17asktom.html. Nun, da ich sehe, wie lange mein Beitrag ist, sollte ich wahrscheinlich gerade gebucht diese Links ...

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; 

Schritt 1: Ihre Abfrage mit order by

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

Schritt 3 : select * from () where rnum >= :MIN_ROW_TO_FETCH; setzen 1 in 2 und 2 in 3