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 ROWSgibt an, dass es keinen Offset geben soll (ein Offset von Null).FETCH NEXT 3 ROWS ONLYerhä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 | +-----------+---------+