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 OFFSETLa 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, doncOFFSET 0commence à la première ligne.LIMIT 10, 5retourne 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 formeLIMIT 5 OFFSET 10.
LIMITsansORDER BYest non déterministe. SansORDER BYexplicite, 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 toujoursLIMITàORDER BYlorsque 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: 85Notez 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: 88Construire 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 pagesPièges courants
- Pas d'
ORDER BY, pas de garantie. Comme indiqué ci-dessus,LIMITne retourne une tranche stable que lorsqu'il est associé à unORDER BYsur une colonne unique (ou sans égalité). - Les grands offsets sont lents.
LIMIT 20 OFFSET 100000oblige quand même MySQL à parcourir et ignorer 100 000 lignes. Pour la pagination en profondeur, préférez la pagination par jeu de clés —WHERE id > :lastSeenId ORDER BY id LIMIT 20— qui utilise l'index pour sauter directement au bon endroit. VoirWHERE. OFFSETne peut pas être utilisé seul. MySQL exige unLIMITchaque fois que vous utilisezOFFSET. 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) * $perPageci-dessus.