W3docs

MySQL Limit

Aprende a usar la cláusula LIMIT de MySQL en Python para limitar resultados, implementar paginación y manejar grandes conjuntos de datos eficientemente.

La cláusula LIMIT controla cuántas filas devuelve una consulta SELECT. Cuando trabajas con tablas grandes — miles o millones de filas — obtener todos los registros a la vez desperdicia memoria y ralentiza tu aplicación. LIMIT te permite recuperar solo los registros que realmente necesitas.

Este capítulo muestra cómo usar LIMIT en Python con el paquete mysql-connector-python, incluyendo la paginación con OFFSET, la combinación de LIMIT con ORDER BY y las mejores prácticas para el manejo de errores.

Requisitos previos

Asegúrate de que el conector MySQL esté instalado antes de ejecutar cualquiera de los ejemplos:

pip install mysql-connector-python

Todos los ejemplos asumen que existe una tabla customers en una base de datos llamada mydatabase. Puedes crearla siguiendo el capítulo Python MySQL Create Table.

Cómo funciona la cláusula LIMIT

La sintaxis básica restringe el conjunto de resultados a un número fijo de filas:

SELECT * FROM table_name LIMIT n;

Para omitir un número de filas antes de comenzar el conjunto de resultados, añade OFFSET:

SELECT * FROM table_name LIMIT n OFFSET m;

OFFSET m significa "omitir las primeras m filas". Esta es la base de la navegación página a página a través de grandes conjuntos de datos.

Obtener un número fijo de filas

El ejemplo siguiente se conecta a una base de datos MySQL y recupera solo los primeros cinco clientes:

Recuperar las primeras 5 filas con LIMIT

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )

    mycursor = mydb.cursor()
    mycursor.execute("SELECT * FROM customers LIMIT 5")

    results = mycursor.fetchall()

    for row in results:
        print(row)

except Error as e:
    print(f"Error: {e}")
finally:
    if mycursor:
        mycursor.close()
    if mydb.is_connected():
        mydb.close()

El método fetchall() devuelve una lista de tuplas — una tupla por fila. Como la consulta ya limita los resultados a cinco filas, la lista contendrá como máximo cinco elementos independientemente del número total de filas en la tabla.

Usar LIMIT con OFFSET para paginación

OFFSET desplaza la fila de inicio del resultado. Combinado con LIMIT, permite implementar paginación: la página 1 muestra las filas 1–10, la página 2 muestra las filas 11–20, y así sucesivamente.

La fórmula es: OFFSET = (page_number - 1) * page_size.

Recuperar la página 2 de resultados (filas 11–20)

import mysql.connector
from mysql.connector import Error

page_number = 2
page_size = 10
offset = (page_number - 1) * page_size  # evaluates to 10

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )

    mycursor = mydb.cursor()

    sql = "SELECT * FROM customers LIMIT %s OFFSET %s"
    mycursor.execute(sql, (page_size, offset))

    results = mycursor.fetchall()

    for row in results:
        print(row)

except Error as e:
    print(f"Error: {e}")
finally:
    if mycursor:
        mycursor.close()
    if mydb.is_connected():
        mydb.close()

Los marcadores de posición %s son completados por el driver del conector, que maneja los valores de forma segura y previene la inyección SQL. Nunca construyas los valores de LIMIT u OFFSET concatenando cadenas directamente en la consulta.

Combinar LIMIT con ORDER BY

Sin ORDER BY, la base de datos puede devolver filas en cualquier orden. Cuando usas LIMIT casi siempre querrás un orden predecible — de lo contrario, la página 1 y la página 2 podrían contener filas superpuestas o arbitrarias.

Recuperar los 5 clientes añadidos más recientemente

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )

    mycursor = mydb.cursor()

    # Sort by id descending so the newest rows come first, then take 5
    mycursor.execute("SELECT * FROM customers ORDER BY id DESC LIMIT 5")

    results = mycursor.fetchall()

    for row in results:
        print(row)

except Error as e:
    print(f"Error: {e}")
finally:
    if mycursor:
        mycursor.close()
    if mydb.is_connected():
        mydb.close()

En MySQL el orden de evaluación es FROMWHEREORDER BYLIMIT, por lo que LIMIT siempre opera sobre el conjunto de resultados ordenado.

Obtener una sola fila con fetchone()

Cuando sabes que solo necesitas una fila — como buscar un registro por clave primaria — puedes limitar la consulta a una fila y usar fetchone() en lugar de fetchall(). Esto evita asignar una lista para un resultado que nunca utilizarás:

Recuperar una sola fila

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )

    mycursor = mydb.cursor()
    mycursor.execute("SELECT * FROM customers LIMIT 1")

    row = mycursor.fetchone()

    if row:
        print(row)
    else:
        print("No records found.")

except Error as e:
    print(f"Error: {e}")
finally:
    if mycursor:
        mycursor.close()
    if mydb.is_connected():
        mydb.close()

fetchone() devuelve una sola tupla o None si el conjunto de resultados está vacío.

Crear una función de paginación reutilizable

En aplicaciones reales es conveniente encapsular la lógica de paginación en una función para que el código que la llama permanezca limpio:

Helper reutilizable paginate()

import mysql.connector
from mysql.connector import Error

def paginate(cursor, table, page, page_size=10):
    """Return one page of rows from *table*.

    Args:
        cursor:    An active mysql.connector cursor.
        table:     Name of the table to query (string).
        page:      1-based page number.
        page_size: Number of rows per page (default 10).

    Returns:
        A list of row tuples, or an empty list when no rows remain.
    """
    offset = (page - 1) * page_size
    # Table names cannot be parameterised, so validate the name first.
    if not table.isidentifier():
        raise ValueError(f"Invalid table name: {table!r}")
    sql = f"SELECT * FROM `{table}` LIMIT %s OFFSET %s"
    cursor.execute(sql, (page_size, offset))
    return cursor.fetchall()


try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    # Print the first three pages
    for page in range(1, 4):
        rows = paginate(mycursor, "customers", page=page, page_size=5)
        if not rows:
            print(f"Page {page}: no more rows.")
            break
        print(f"--- Page {page} ---")
        for row in rows:
            print(row)

except Error as e:
    print(f"Error: {e}")
finally:
    if mycursor:
        mycursor.close()
    if mydb.is_connected():
        mydb.close()

Ten en cuenta que los nombres de tabla no pueden pasarse como parámetros %s — el conector no admite parametrizar identificadores. La comprobación isidentifier() protege contra la inyección a través del argumento del nombre de tabla.

Errores comunes

LIMIT sin ORDER BY da resultados impredecibles. MySQL no garantiza un orden de filas estable a menos que especifiques ORDER BY. Dos consultas idénticas podrían devolver filas diferentes si la tabla se modifica entre llamadas.

Los valores grandes de OFFSET son lentos. LIMIT 10 OFFSET 1000000 sigue obligando a MySQL a escanear y descartar un millón de filas antes de devolver diez. Para la paginación profunda en tablas muy grandes, considera la paginación por conjunto de claves (también llamada paginación basada en cursor): registra el último id visto en la página anterior y usa WHERE id > last_id LIMIT 10.

No construyas valores de LIMIT mediante concatenación de cadenas. Usa marcadores de posición %s o, si el valor se calcula en Python, asegúrate de que sea un entero simple antes de incrustarlo en la cadena SQL.

Resumen

ObjetivoPatrón SQL
Primeras N filasSELECT ... LIMIT N
Omitir M filas, tomar NSELECT ... LIMIT N OFFSET M
Página P de tamaño NLIMIT N OFFSET (P-1)*N
Solo una filaSELECT ... LIMIT 1 + fetchone()
Primeras N ordenadasSELECT ... ORDER BY col LIMIT N

Capítulos relacionados

Was this page helpful?