7 Stimmen

Paging mit Oracle und Sql-Server und generisches Paging-Verfahren

Ich möchte das Blättern in einem Gridview oder in einer html-Tabelle implementieren, die ich mit Ajax füllen werde. Wie sollte ich Abfragen schreiben, um das Blättern zu unterstützen? Wenn zum Beispiel die Seitengröße 20 ist und der Benutzer auf Seite 3 klickt, müssen die Zeilen zwischen 41 und 60 in der Tabelle angezeigt werden. Zunächst kann ich alle Datensätze abrufen und in den Cache stellen, aber ich denke, das ist der falsche Weg. Denn die Daten können sehr groß sein und die Daten können sich in anderen Sitzungen ändern. Wie kann ich das also implementieren? Gibt es eine generische Methode (für alle Datenbanken)?

17voto

Wie bereits von anderen vorgeschlagen, können Sie in Oracle rownum verwenden. Das ist allerdings etwas kompliziert und Sie müssen Ihre Abfrage zweimal verschachteln.

Zum Beispiel, um die Abfrage zu paginieren

select first_name from some_table order by first_name

müssen Sie sie wie folgt verschachteln

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 ist, dass rownum bestimmt wird nach die Where-Klausel und vor die Auftragsklausel. Um zu sehen, was ich meine, können Sie Folgendes abfragen

select rownum,first_name from some_table order by first_name

und Sie bekommen vielleicht

4   Diane
2   Norm
3   Sam
1   Woody

Das liegt daran, dass Orakel die Where-Klausel auswertet (in diesem Fall keine), dann Rownums zuweist und die Ergebnisse nach First_name sortiert. Sie müssen die Abfrage verschachteln, damit sie die zugewiesene rownum verwendet nach die Zeilen sortiert wurden.

Die zweite Verschachtelung hat damit zu tun, wie rownum in einer where-Bedingung behandelt wird. Wenn Sie "where rownum > 100" abfragen, erhalten Sie grundsätzlich keine Ergebnisse. Es ist ein Henne-Ei-Ding, bei dem es keine Zeilen zurückgeben kann, bis es rownum > 100 findet, aber da es keine Zeilen zurückgibt, wird rownum nie erhöht, so dass es nie bis 100 zählt. Igitt. Die zweite Ebene der Verschachtelung löst dieses Problem. Beachten Sie, dass die Spalte rownum an dieser Stelle mit einem Alias versehen werden muss.

Schließlich muss Ihre order by-Klausel die Abfrage deterministisch machen. Wenn Sie zum Beispiel John Doe und John Smith haben und nur nach dem Vornamen ordnen, können die beiden von einer Ausführung der Abfrage zur nächsten den Platz 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 . Jetzt, wo ich sehe, wie lang mein Beitrag ist, hätte ich wohl einfach die Links posten sollen...

4voto

Tony Andrews Punkte 125904

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

Vielleicht können Sie diese Unterschiede mit einer Funktion kapseln, die eine gegebene SQL-Anweisung und erste und letzte Zeilennummern nimmt und das entsprechende paginierte SQL für das Ziel-DBMS generiert - d.h. etwas wie:

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

was Folgendes ergeben würde

'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 der Sie umgehen müssen.

1voto

Ich glaube, beide haben eine analytische Funktion ROWNUM. Verwenden Sie diese und Sie werden identisch sein.

Bei Oracle ist es aquí

ROW_NUMBER

Ja, ich habe gerade überprüft, dass ROW_NUMBER in beiden die gleiche Funktion ist.

1voto

Gary Myers Punkte 34373

"Weil ... Daten aus anderen Sitzungen geändert werden können." Was soll in diesem Fall geschehen?

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

Um 10:31 Uhr werden 3 neue Zeilen hinzugefügt (die zehn Zeilen, die der Benutzer sieht, sind also nicht mehr die neuesten).

Um 10:32 Uhr fordert der Benutzer dann die nächsten zehn Einträge an.

Möchten Sie, dass das neue Set die drei, die vom 8/9/10 auf den 11/12/13 verschoben wurden, enthält? Wenn nicht, können Sie in Oracle die Daten so auswählen, wie sie um 10:30 Uhr waren.

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

Sie brauchen immer noch die row_number-Logik, z. B.

 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

1voto

Ashis Punkte 11
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; 1 in 2 und 2 in 3 setzen

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X