Paginierung wird häufig in Anwendungen verwendet, in denen der Benutzer auf Zurück klicken kann /Weiter um durch die Seiten zu navigieren, aus denen sich die Ergebnisse zusammensetzen, oder klicken Sie auf eine Seitennummer, um direkt zu einer bestimmten Seite zu gelangen.
Beim Ausführen von Abfragen in SQL Server können Sie die Ergebnisse paginieren, indem Sie OFFSET
verwenden und FETCH
Argumente von ORDER BY
Klausel. Diese Argumente wurden in SQL Server 2012 eingeführt, daher können Sie diese Technik verwenden, wenn Sie über SQL Server 2012 oder höher verfügen.
In diesem Zusammenhang teilen Sie bei der Paginierung die Abfrageergebnisse in kleinere Abschnitte auf, wobei jeder Abschnitt dort fortgesetzt wird, wo der vorherige aufgehört hat. Wenn eine Abfrage beispielsweise 1000 Zeilen zurückgibt, können Sie sie so paginieren, dass sie in Gruppen von 100 zurückgegeben werden. Eine Anwendung kann die Seitennummer und die Seitengröße an SQL Server übergeben, und SQL Server kann sie dann verwenden, um nur die zurückzugeben Daten für die angeforderte Seite.
Beispiel 1 – Keine Paginierung
Lassen Sie uns zuerst eine Abfrage ausführen, die alle Zeilen in einer Tabelle zurückgibt:
SELECT * FROM Genres ORDER BY GenreId;
Ergebnis:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 1 | Rock | | 2 | Jazz | | 3 | Country | | 4 | Pop | | 5 | Blues | | 6 | Hip Hop | | 7 | Rap | | 8 | Punk | +-----------+---------+
Dieses Beispiel verwendet keine Paginierung – alle Ergebnisse werden angezeigt.
Diese Ergebnismenge ist so klein, dass normalerweise keine Paginierung erforderlich wäre, aber für die Zwecke dieses Artikels sollten wir sie paginieren.
Beispiel 2 – Anzeige der ersten 3 Ergebnisse
Dieses Beispiel zeigt die ersten drei Ergebnisse:
SELECT * FROM Genres ORDER BY GenreId OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY;
Ergebnis:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 1 | Rock | | 2 | Jazz | | 3 | Country | +-----------+---------+
In diesem Fall gebe ich an, dass die Ergebnisse beim ersten Ergebnis beginnen und die nächsten drei Zeilen anzeigen sollen. Dies geschieht wie folgt:
OFFSET 0 ROWS
gibt an, dass es keinen Offset geben soll (ein Offset von Null).FETCH NEXT 3 ROWS ONLY
erhält die nächsten drei Zeilen vom Offset. Da ich einen Offset von Null angegeben habe, werden die ersten drei Zeilen abgerufen.
Wenn wir nur die Top-3-Ergebnisse wollten, hätten wir dasselbe Ergebnis mit TOP
erzielen können -Klausel, anstatt die Offset- und Abrufwerte anzugeben. Dies hätte uns jedoch nicht erlaubt, den nächsten Teil zu machen.
Beispiel 3 – Anzeige der nächsten 3 Ergebnisse
Lassen Sie uns nun die nächsten drei Ergebnisse anzeigen:
SELECT * FROM Genres ORDER BY GenreId OFFSET 3 ROWS FETCH NEXT 3 ROWS ONLY;
Ergebnis:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 4 | Pop | | 5 | Blues | | 6 | Hip Hop | +-----------+---------+
Das einzige, was ich geändert habe, war der Offset.
Die Offset- und Abrufwerte können auch ein Ausdruck sein, der als Variable, Parameter oder konstante skalare Unterabfrage bereitgestellt wird. Wenn eine Unterabfrage verwendet wird, kann sie nicht auf Spalten verweisen, die im äußeren Abfragebereich definiert sind (sie kann nicht mit der äußeren Abfrage korreliert werden).
Die folgenden Beispiele verwenden Ausdrücke, um zwei Ansätze zum Paginieren der Ergebnisse zu zeigen.
Beispiel 4 – Paginierung nach Zeilennummer
Dieses Beispiel verwendet Ausdrücke, um die Zeile anzugeben Startnummer.
DECLARE @StartRow int = 1, @RowsPerPage int = 3; SELECT * FROM Genres ORDER BY GenreId ASC OFFSET @StartRow - 1 ROWS FETCH NEXT @RowsPerPage ROWS ONLY;
Ergebnis:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 1 | Rock | | 2 | Jazz | | 3 | Country | +-----------+---------+
Hier verwende ich @StartRow int = 1
um anzugeben, dass die Ergebnisse in der ersten Zeile beginnen sollen.
Folgendes passiert, wenn ich diesen Wert auf 2
erhöhe .
DECLARE @StartRow int = 2, @RowsPerPage int = 3; SELECT * FROM Genres ORDER BY GenreId ASC OFFSET @StartRow - 1 ROWS FETCH NEXT @RowsPerPage ROWS ONLY;
Ergebnis:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 2 | Jazz | | 3 | Country | | 4 | Pop | +-----------+---------+
Es beginnt in der zweiten Reihe. Mit dieser Methode kann ich die genaue Zeile angeben, bei der ich beginnen soll.
Beispiel 5 – Paginierung nach Seitenzahl
Dieses Beispiel ist fast identisch mit dem vorherigen Beispiel, mit der Ausnahme, dass Sie die Seitennummer anstelle der Zeilennummer angeben können.
DECLARE @PageNumber int = 1, @RowsPerPage int = 3; SELECT * FROM Genres ORDER BY GenreId ASC OFFSET (@PageNumber - 1) * @RowsPerPage ROWS FETCH NEXT @RowsPerPage ROWS ONLY;
Ergebnis:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 1 | Rock | | 2 | Jazz | | 3 | Country | +-----------+---------+
Das erste Ergebnis ist also dasselbe. Sehen wir uns jedoch an, was passiert, wenn wir @PageNumber
erhöhen zu 2
(Ich habe diese Variable umbenannt, um ihren neuen Zweck widerzuspiegeln).
DECLARE @PageNumber int = 2, @RowsPerPage int = 3; SELECT * FROM Genres ORDER BY GenreId ASC OFFSET (@PageNumber - 1) * @RowsPerPage ROWS FETCH NEXT @RowsPerPage ROWS ONLY;
Ergebnis:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 4 | Pop | | 5 | Blues | | 6 | Hip Hop | +-----------+---------+
Diesmal beginnen die Ergebnisse in der vierten Reihe. Mit dieser Methode können Sie also einfach die Seitennummer statt der Zeilennummer übergeben.
Beispiel 6 – Paginierungsschleife
Zum Abschluss ist hier ein kurzes Beispiel, das alle Seiten durchläuft und die Anfangszeilennummer für jede Iteration angibt:
DECLARE @StartRow int = 1, @RowsPerPage int = 3; WHILE (SELECT COUNT(*) FROM Genres) >= @StartRow BEGIN SELECT * FROM Genres ORDER BY GenreId ASC OFFSET @StartRow - 1 ROWS FETCH NEXT @RowsPerPage ROWS ONLY; SET @StartRow = @StartRow + @RowsPerPage; CONTINUE END;
Ergebnis:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 1 | Rock | | 2 | Jazz | | 3 | Country | +-----------+---------+ (3 rows affected) +-----------+---------+ | GenreId | Genre | |-----------+---------| | 4 | Pop | | 5 | Blues | | 6 | Hip Hop | +-----------+---------+ (3 rows affected) +-----------+---------+ | GenreId | Genre | |-----------+---------| | 7 | Rap | | 8 | Punk | +-----------+---------+ (2 rows affected)
Beispiel 7 – REIHE vs. REIHE
Wenn Sie auf Code stoßen, der ROW
verwendet statt ROWS
, machen beide Argumente dasselbe. Sie sind Synonyme und dienen der ANSI-Kompatibilität.
Hier ist das erste Beispiel auf dieser Seite, aber mit ROW
statt ROWS
.
SELECT * FROM Genres ORDER BY GenreId OFFSET 0 ROW FETCH NEXT 3 ROW ONLY;
Ergebnis:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 1 | Rock | | 2 | Jazz | | 3 | Country | +-----------+---------+
Beispiel 8 – ERSTER vs. NÄCHSTER
Gleiches gilt für FIRST
und NEXT
. Dies sind Synonyme für die ANSI-Kompatibilität.
Hier ist das vorherige Beispiel, aber mit FIRST
statt NEXT
.
SELECT * FROM Genres ORDER BY GenreId OFFSET 0 ROW FETCH FIRST 3 ROW ONLY;
Ergebnis:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 1 | Rock | | 2 | Jazz | | 3 | Country | +-----------+---------+