W3docs

PHP MySQL SELECT avec LIMIT : Guide complet

Apprenez à utiliser la clause LIMIT dans MySQL avec PHP pour récupérer un nombre précis de lignes et paginer vos résultats efficacement.

Dans une base de données, vous souhaitez souvent ne récupérer qu'une partie d'une table — les dix publications les plus récentes, la première page de résultats de recherche, un seul « meilleur score » — plutôt que toutes les lignes. La clause LIMIT dans une instruction MySQL SELECT plafonne le nombre de lignes retournées par la requête. Combinée à un OFFSET, elle constitue le fondement de la pagination : servir de grands ensembles de résultats une page à la fois plutôt que de charger des milliers de lignes en mémoire.

Ce chapitre couvre la syntaxe de LIMIT, le OFFSET permettant de sauter des lignes, la construction sécurisée de la pagination avec des requêtes préparées, ainsi que les pièges courants. Il suppose que vous savez déjà vous connecter à MySQL et exécuter un SELECT de base.

Syntaxe de SELECT avec LIMIT

La forme de base définit un nombre maximum de lignes à retourner :

SELECT column1, column2, ... FROM table_name LIMIT row_count;

Pour également sauter des lignes au début du jeu de résultats, ajoutez un offset. MySQL prend en charge deux syntaxes équivalentes :

SELECT ... FROM table_name LIMIT offset, row_count;   -- offset first
SELECT ... FROM table_name LIMIT row_count OFFSET offset;  -- explicit OFFSET

La signification de chaque partie :

  • row_count — le nombre maximum de lignes à retourner.
  • offset — combien de lignes sauter avant de commencer à retourner des lignes. L'offset est à base zéro, donc OFFSET 0 commence à la première ligne.
  • LIMIT 10, 5 retourne 5 lignes à partir de la onzième (c'est-à-dire les lignes 11–15). La même requête se lit plus naturellement sous la forme LIMIT 5 OFFSET 10.

LIMIT sans ORDER BY est non déterministe. Sans ORDER BY explicite, MySQL est libre de retourner les lignes dans n'importe quel ordre, de sorte que « les 2 premières lignes » peuvent différer d'une exécution à l'autre. Associez toujours LIMIT à ORDER BY lorsque l'ordre des lignes est important.

Exemple : récupérer les premières lignes

Considérons une table nommée students :

+----+---------+--------+-------+
| id | name    | class  | marks |
+----+---------+--------+-------+
|  1 | John    | 10     | 90    |
|  2 | Michael | 9      | 85    |
|  3 | Jessica | 8      | 80    |
|  4 | Sarah   | 10     | 88    |
|  5 | David   | 9      | 72    |
+----+---------+--------+-------+

Pour récupérer les deux premiers étudiants (ordonnés par id afin que le résultat soit stable) :

<?php
$conn = mysqli_connect("localhost", "username", "password", "database");

$query = "SELECT id, name, class, marks FROM students ORDER BY id LIMIT 2";
$result = mysqli_query($conn, $query);

while ($row = mysqli_fetch_assoc($result)) {
    echo "ID: {$row['id']} Name: {$row['name']} Class: {$row['class']} Marks: {$row['marks']}<br>";
}

mysqli_close($conn);
?>

Résultat :

ID: 1 Name: John Class: 10 Marks: 90
ID: 2 Name: Michael Class: 9 Marks: 85

Notez l'utilisation de mysqli_fetch_assoc() (tableau associatif uniquement) plutôt que mysqli_fetch_array(), qui retourne à la fois des clés numériques et des clés de type chaîne, allouant ainsi deux fois plus de mémoire pour les mêmes données.

Sauter des lignes avec OFFSET

Pour obtenir la deuxième page de deux étudiants — les lignes 3 et 4 — il faut sauter les deux premières :

<?php
$conn = mysqli_connect("localhost", "username", "password", "database");

$query = "SELECT id, name, marks FROM students ORDER BY id LIMIT 2 OFFSET 2";
$result = mysqli_query($conn, $query);

while ($row = mysqli_fetch_assoc($result)) {
    echo "ID: {$row['id']} Name: {$row['name']} Marks: {$row['marks']}<br>";
}

mysqli_close($conn);
?>

Résultat :

ID: 3 Name: Jessica Marks: 80
ID: 4 Name: Sarah Marks: 88

Construire une pagination sécurisée

Pour une pagination réelle, le numéro de page provient de la saisie de l'utilisateur (une URL comme ?page=3), donc l'offset ne doit jamais être concaténé directement dans le SQL. Utilisez une requête préparée avec des paramètres entiers liés :

<?php
$conn = mysqli_connect("localhost", "username", "password", "database");

$perPage = 2;
$page    = max(1, (int) ($_GET['page'] ?? 1)); // force a positive integer
$offset  = ($page - 1) * $perPage;

$stmt = mysqli_prepare(
    $conn,
    "SELECT id, name, marks FROM students ORDER BY id LIMIT ? OFFSET ?"
);
mysqli_stmt_bind_param($stmt, "ii", $perPage, $offset); // "ii" = two integers
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);

while ($row = mysqli_fetch_assoc($result)) {
    echo "ID: {$row['id']} Name: {$row['name']} Marks: {$row['marks']}<br>";
}

mysqli_close($conn);
?>

Le transtypage de la page en (int) et sa liaison en tant qu'entier ("ii") préviennent les injections SQL, puisque LIMIT/OFFSET n'acceptent de toute façon que des nombres.

Pour afficher « Page 3 sur N », vous avez également besoin du nombre total de lignes. Exécutez une requête COUNT(*) séparée et divisez par la taille de la page :

$total = (int) mysqli_fetch_row(
    mysqli_query($conn, "SELECT COUNT(*) FROM students")
)[0];
$pageCount = (int) ceil($total / $perPage); // 5 rows / 2 per page = 3 pages

Pièges courants

  • Pas d'ORDER BY, pas de garantie. Comme indiqué ci-dessus, LIMIT ne retourne une tranche stable que lorsqu'il est associé à un ORDER BY sur une colonne unique (ou sans égalité).
  • Les grands offsets sont lents. LIMIT 20 OFFSET 100000 oblige quand même MySQL à parcourir et ignorer 100 000 lignes. Pour la pagination en profondeur, préférez la pagination par jeu de clésWHERE id > :lastSeenId ORDER BY id LIMIT 20 — qui utilise l'index pour sauter directement au bon endroit. Voir WHERE.
  • OFFSET ne peut pas être utilisé seul. MySQL exige un LIMIT chaque fois que vous utilisez OFFSET. Pour sauter des lignes et retourner « tout le reste », utilisez une limite très grande : LIMIT 18446744073709551615 OFFSET 10.
  • Les pages sont indexées à zéro en interne. Une erreur de décalage courante consiste à oublier que la page 1 correspond à OFFSET 0, d'où le calcul ($page - 1) * $perPage ci-dessus.

Pratique

Pratique
Quel est le rôle du mot-clé 'LIMIT' dans MySQL ?
Quel est le rôle du mot-clé 'LIMIT' dans MySQL ?
Was this page helpful?