W3docs

MySQL Limit

Aprenda a usar a cláusula MySQL LIMIT em Python para limitar resultados, implementar paginação e lidar com grandes conjuntos de dados.

A cláusula LIMIT controla quantas linhas uma consulta SELECT retorna. Ao trabalhar com tabelas grandes — com milhares ou milhões de linhas — buscar todos os registros de uma vez desperdiça memória e torna a aplicação mais lenta. O LIMIT permite recuperar apenas os registros que você realmente precisa.

Este capítulo mostra como usar o LIMIT em Python com o pacote mysql-connector-python, incluindo paginação com OFFSET, combinação de LIMIT com ORDER BY e boas práticas para tratamento de erros.

Pré-requisitos

Certifique-se de que o conector MySQL está instalado antes de executar qualquer um dos exemplos:

pip install mysql-connector-python

Todos os exemplos assumem que existe uma tabela customers em um banco de dados chamado mydatabase. Você pode criá-la seguindo o capítulo Python MySQL Create Table.

Como a cláusula LIMIT funciona

A sintaxe básica restringe o conjunto de resultados a um número fixo de linhas:

SELECT * FROM table_name LIMIT n;

Para ignorar um número de linhas antes de iniciar o conjunto de resultados, adicione OFFSET:

SELECT * FROM table_name LIMIT n OFFSET m;

OFFSET m significa "ignorar as primeiras m linhas". Esta é a base da navegação página a página por grandes conjuntos de dados.

Buscando um número fixo de linhas

O exemplo abaixo conecta-se a um banco de dados MySQL e recupera apenas os cinco primeiros clientes:

Recuperar as primeiras 5 linhas com 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()

O método fetchall() retorna uma lista de tuplas — uma tupla por linha. Como a consulta já limita os resultados a cinco linhas, a lista conterá no máximo cinco itens, independentemente do número total de linhas na tabela.

Usando LIMIT com OFFSET para paginação

OFFSET desloca a linha inicial do resultado. Combinado com LIMIT, permite implementar paginação: a página 1 exibe as linhas 1–10, a página 2 exibe as linhas 11–20, e assim por diante.

A fórmula é: OFFSET = (page_number - 1) * page_size.

Recuperar a página 2 dos resultados (linhas 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()

Os marcadores %s são preenchidos pelo driver do conector, que trata os valores com segurança e previne injeção de SQL. Nunca construa os valores de LIMIT ou OFFSET concatenando strings diretamente na consulta.

Combinando LIMIT com ORDER BY

Sem ORDER BY, o banco de dados pode retornar as linhas em qualquer ordem. Quando você usa LIMIT, quase sempre deseja uma ordem previsível — caso contrário, a página 1 e a página 2 podem conter linhas sobrepostas ou arbitrárias.

Recuperar os 5 clientes adicionados mais recentemente

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

No MySQL, a ordem de avaliação é FROMWHEREORDER BYLIMIT, portanto o LIMIT sempre opera sobre o conjunto de resultados ordenado.

Buscando uma única linha com fetchone()

Quando você sabe que precisa de apenas uma linha — como ao buscar um registro pela chave primária — pode limitar a consulta a uma linha e usar fetchone() em vez de fetchall(). Isso evita alocar uma lista para um resultado que nunca será utilizado:

Recuperar uma única linha

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() retorna uma única tupla ou None se o conjunto de resultados estiver vazio.

Criando uma função de paginação reutilizável

Em aplicações reais, é conveniente encapsular a lógica de paginação em uma função para manter o código chamador limpo:

Helper paginate() reutilizável

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

Observe que nomes de tabelas não podem ser passados como parâmetros %s — o conector não suporta a parametrização de identificadores. A verificação com isidentifier() protege contra injeção por meio do argumento com o nome da tabela.

Erros comuns

LIMIT sem ORDER BY produz resultados imprevisíveis. O MySQL não garante uma ordem estável de linhas a menos que você especifique ORDER BY. Duas consultas idênticas podem retornar linhas diferentes se a tabela for modificada entre as chamadas.

Valores grandes de OFFSET são lentos. LIMIT 10 OFFSET 1000000 ainda faz o MySQL varrer e descartar um milhão de linhas antes de retornar dez. Para paginação profunda em tabelas muito grandes, considere a paginação por keyset (também chamada de paginação baseada em cursor): registre o último id visto na página anterior e use WHERE id > last_id LIMIT 10.

Não construa valores de LIMIT por concatenação de strings. Use marcadores %s ou, se o valor for calculado em Python, certifique-se de que seja um inteiro simples antes de incorporá-lo na string SQL.

Resumo

ObjetivoPadrão SQL
Primeiras N linhasSELECT ... LIMIT N
Ignorar M linhas, buscar NSELECT ... LIMIT N OFFSET M
Página P de tamanho NLIMIT N OFFSET (P-1)*N
Apenas uma linhaSELECT ... LIMIT 1 + fetchone()
Primeiras N ordenadasSELECT ... ORDER BY col LIMIT N

Capítulos relacionados

Was this page helpful?