Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Pagination dans SQL Server à l'aide de OFFSET/FETCH

La pagination est souvent utilisée dans les applications où l'utilisateur peut cliquer sur Précédent /Suivant pour naviguer dans les pages qui composent les résultats, ou cliquez sur un numéro de page pour accéder directement à une page spécifique.

Lors de l'exécution de requêtes dans SQL Server, vous pouvez paginer les résultats en utilisant le OFFSET et FETCH arguments du ORDER BY clause. Ces arguments ont été introduits dans SQL Server 2012, vous pouvez donc utiliser cette technique si vous avez SQL Server 2012 ou supérieur.

Dans ce contexte, la pagination est l'endroit où vous divisez les résultats de la requête en plus petits morceaux, chaque morceau continuant là où le précédent s'est terminé. Par exemple, si une requête renvoie 1 000 lignes, vous pouvez les paginer afin qu'elles soient renvoyées par groupes de 100. Une application peut transmettre le numéro de page et la taille de page à SQL Server, et SQL Server peut ensuite l'utiliser pour renvoyer uniquement le données pour la page demandée.

Exemple 1 - Pas de pagination

Commençons par exécuter une requête qui renvoie toutes les lignes d'une table :

SELECT *
FROM Genres
ORDER BY GenreId;

Résultat :

+-----------+---------+
| GenreId   | Genre   |
|-----------+---------|
| 1         | Rock    |
| 2         | Jazz    |
| 3         | Country |
| 4         | Pop     |
| 5         | Blues   |
| 6         | Hip Hop |
| 7         | Rap     |
| 8         | Punk    |
+-----------+---------+

Cet exemple n'utilise aucune pagination - tous les résultats sont affichés.

Cet ensemble de résultats est si petit qu'il ne nécessite normalement pas de pagination, mais pour les besoins de cet article, paginons-le.

Exemple 2 - Afficher les 3 premiers résultats

Cet exemple affiche les trois premiers résultats :

SELECT *
FROM Genres
ORDER BY GenreId
  OFFSET 0 ROWS
  FETCH NEXT 3 ROWS ONLY;

Résultat :

+-----------+---------+
| GenreId   | Genre   |
|-----------+---------|
| 1         | Rock    |
| 2         | Jazz    |
| 3         | Country |
+-----------+---------+

Dans ce cas, je précise que les résultats doivent commencer au premier résultat et afficher les trois lignes suivantes. Ceci est fait en utilisant ce qui suit :

  • OFFSET 0 ROWS spécifie qu'il ne doit y avoir aucun décalage (un décalage de zéro).
  • FETCH NEXT 3 ROWS ONLY obtient les trois lignes suivantes à partir du décalage. Comme j'ai spécifié un décalage de zéro, les trois premières lignes sont récupérées.

Si tout ce que nous voulions était les 3 meilleurs résultats, nous aurions pu obtenir le même résultat en utilisant le TOP au lieu de spécifier les valeurs de décalage et d'extraction. Cependant, cela ne nous aurait pas permis de faire la partie suivante.

Exemple 3 - Afficher les 3 résultats suivants

Maintenant, affichons les trois résultats suivants :

SELECT *
FROM Genres
ORDER BY GenreId
  OFFSET 3 ROWS
  FETCH NEXT 3 ROWS ONLY;

Résultat :

+-----------+---------+
| GenreId   | Genre   |
|-----------+---------|
| 4         | Pop     |
| 5         | Blues   |
| 6         | Hip Hop |
+-----------+---------+

Donc, la seule chose que j'ai changée, c'est le décalage.

Les valeurs de décalage et d'extraction peuvent également être une expression fournie sous forme de variable, de paramètre ou de sous-requête scalaire constante. Lorsqu'une sous-requête est utilisée, elle ne peut référencer aucune colonne définie dans la portée de la requête externe (elle ne peut pas être corrélée avec la requête externe).

Les exemples suivants utilisent des expressions pour montrer deux approches de pagination des résultats.

Exemple 4 - Pagination par numéro de ligne

Cet exemple utilise des expressions pour spécifier la ligne numéro de départ.

DECLARE 
  @StartRow int = 1,
  @RowsPerPage int = 3;
  
SELECT *  
FROM Genres
ORDER BY GenreId ASC
    OFFSET @StartRow - 1 ROWS
    FETCH NEXT @RowsPerPage ROWS ONLY;

Résultat :

+-----------+---------+
| GenreId   | Genre   |
|-----------+---------|
| 1         | Rock    |
| 2         | Jazz    |
| 3         | Country |
+-----------+---------+

Ici, j'utilise @StartRow int = 1 pour spécifier que les résultats doivent commencer à la première ligne.

Voici ce qui se passe si j'incrémente cette valeur à 2 .

DECLARE 
  @StartRow int = 2,
  @RowsPerPage int = 3;
  
SELECT *  
FROM Genres
ORDER BY GenreId ASC
    OFFSET @StartRow - 1 ROWS
    FETCH NEXT @RowsPerPage ROWS ONLY;

Résultat :

+-----------+---------+
| GenreId   | Genre   |
|-----------+---------|
| 2         | Jazz    |
| 3         | Country |
| 4         | Pop     |
+-----------+---------+

Il commence au deuxième rang. En utilisant cette méthode, je peux spécifier la ligne exacte à partir de laquelle commencer.

Exemple 5 - Pagination par numéro de page

Cet exemple est presque identique à l'exemple précédent, sauf qu'il vous permet de spécifier le numéro de page, par opposition au numéro de ligne.

DECLARE 
  @PageNumber int = 1,
  @RowsPerPage int = 3;
  
SELECT *  
FROM Genres
ORDER BY GenreId ASC
    OFFSET (@PageNumber - 1) * @RowsPerPage ROWS
    FETCH NEXT @RowsPerPage ROWS ONLY;

Résultat :

+-----------+---------+
| GenreId   | Genre   |
|-----------+---------|
| 1         | Rock    |
| 2         | Jazz    |
| 3         | Country |
+-----------+---------+

Donc le premier résultat est le même. Cependant, voyons ce qui se passe lorsque nous incrémentons @PageNumber à 2 (J'ai renommé cette variable pour refléter son nouvel objectif).

DECLARE 
  @PageNumber int = 2,
  @RowsPerPage int = 3;
  
SELECT *  
FROM Genres
ORDER BY GenreId ASC
    OFFSET (@PageNumber - 1) * @RowsPerPage ROWS
    FETCH NEXT @RowsPerPage ROWS ONLY;

Résultat :

+-----------+---------+
| GenreId   | Genre   |
|-----------+---------|
| 4         | Pop     |
| 5         | Blues   |
| 6         | Hip Hop |
+-----------+---------+

Cette fois, les résultats commencent à la quatrième ligne. Ainsi, en utilisant cette méthode, vous pouvez simplement transmettre le numéro de page plutôt que le numéro de ligne.

Exemple 6 - Boucle de pagination

Pour finir, voici un exemple rapide qui parcourt toutes les pages et spécifie le numéro de ligne de départ pour chaque itération :

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;

Résultat :

+-----------+---------+
| 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)

Exemple 7 – LIGNE vs LIGNES

Si vous rencontrez du code qui utilise ROW au lieu de ROWS , les deux arguments font la même chose. Ce sont des synonymes et sont fournis pour la compatibilité ANSI.

Voici le premier exemple sur cette page, mais avec ROW au lieu de ROWS .

SELECT *
FROM Genres
ORDER BY GenreId
  OFFSET 0 ROW
  FETCH NEXT 3 ROW ONLY;

Résultat :

+-----------+---------+
| GenreId   | Genre   |
|-----------+---------|
| 1         | Rock    |
| 2         | Jazz    |
| 3         | Country |
+-----------+---------+

Exemple 8 - PREMIER vs SUIVANT

Il en va de même pour FIRST et NEXT . Ce sont des synonymes fournis pour la compatibilité ANSI.

Voici l'exemple précédent mais avec FIRST au lieu de NEXT .

SELECT *
FROM Genres
ORDER BY GenreId
  OFFSET 0 ROW
  FETCH FIRST 3 ROW ONLY;

Résultat :

+-----------+---------+
| GenreId   | Genre   |
|-----------+---------|
| 1         | Rock    |
| 2         | Jazz    |
| 3         | Country |
+-----------+---------+