W3docs

MySQL Limit

Erfahren Sie, wie Sie die MySQL LIMIT-Klausel in Python nutzen, um Abfrageergebnisse zu begrenzen, Paginierung umzusetzen und große Datensätze effizient zu verarbeiten.

Die LIMIT-Klausel steuert, wie viele Zeilen eine SELECT-Abfrage zurückgibt. Wenn Sie mit großen Tabellen arbeiten — Tausende oder Millionen von Zeilen — verschwendet das Abrufen aller Datensätze auf einmal Arbeitsspeicher und verlangsamt Ihre Anwendung. Mit LIMIT rufen Sie nur die Datensätze ab, die Sie tatsächlich benötigen.

Dieses Kapitel zeigt, wie Sie LIMIT in Python mit dem Paket mysql-connector-python verwenden, einschließlich Paginierung mit OFFSET, der Kombination von LIMIT und ORDER BY sowie bewährter Verfahren zur Fehlerbehandlung.

Voraussetzungen

Stellen Sie sicher, dass der MySQL-Connector installiert ist, bevor Sie eines der Beispiele ausführen:

pip install mysql-connector-python

Alle Beispiele setzen voraus, dass eine Tabelle customers in einer Datenbank namens mydatabase vorhanden ist. Sie können eine erstellen, indem Sie dem Kapitel Python MySQL Create Table folgen.

Wie die LIMIT-Klausel funktioniert

Die grundlegende Syntax beschränkt die Ergebnismenge auf eine feste Anzahl von Zeilen:

SELECT * FROM table_name LIMIT n;

Um eine Anzahl von Zeilen zu überspringen, bevor die Ergebnismenge beginnt, fügen Sie OFFSET hinzu:

SELECT * FROM table_name LIMIT n OFFSET m;

OFFSET m bedeutet „überspringe die ersten m Zeilen". Dies ist die Grundlage für die seitenweise Navigation durch große Datensätze.

Eine feste Anzahl von Zeilen abrufen

Das folgende Beispiel stellt eine Verbindung zu einer MySQL-Datenbank her und ruft nur die ersten fünf Kunden ab:

Die ersten 5 Zeilen mit LIMIT abrufen

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

Die Methode fetchall() gibt eine Liste von Tupeln zurück — ein Tupel pro Zeile. Da die Abfrage die Ergebnisse bereits auf fünf Zeilen begrenzt, enthält die Liste unabhängig von der Gesamtzahl der Zeilen in der Tabelle höchstens fünf Einträge.

LIMIT mit OFFSET für Paginierung verwenden

OFFSET verschiebt die Startzeile des Ergebnisses. In Kombination mit LIMIT ermöglicht es die Implementierung von Paginierung: Seite 1 zeigt Zeilen 1–10, Seite 2 zeigt Zeilen 11–20 usw.

Die Formel lautet: OFFSET = (Seitennummer - 1) * Seitengröße.

Seite 2 der Ergebnisse abrufen (Zeilen 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()

Die %s-Platzhalter werden vom Connector-Treiber befüllt, der die Werte sicher verarbeitet und SQL-Injection verhindert. Bauen Sie die LIMIT- oder OFFSET-Werte niemals durch direkte String-Verkettung in die Abfrage ein.

LIMIT mit ORDER BY kombinieren

Ohne ORDER BY kann die Datenbank Zeilen in beliebiger Reihenfolge zurückgeben. Wenn Sie LIMIT verwenden, möchten Sie fast immer eine vorhersehbare Reihenfolge — andernfalls könnten Seite 1 und Seite 2 überlappende oder beliebige Zeilen enthalten.

Die 5 zuletzt hinzugefügten Kunden abrufen

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

In MySQL ist die Auswertungsreihenfolge FROMWHEREORDER BYLIMIT, sodass LIMIT immer auf der sortierten Ergebnismenge operiert.

Eine einzelne Zeile mit fetchone() abrufen

Wenn Sie wissen, dass Sie nur eine Zeile benötigen — etwa beim Nachschlagen eines Datensatzes über den Primärschlüssel — können Sie die Abfrage auf eine Zeile begrenzen und fetchone() statt fetchall() verwenden. So vermeiden Sie die Zuweisung einer Liste für ein Ergebnis, das Sie nie nutzen werden:

Eine einzelne Zeile abrufen

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() gibt ein einzelnes Tupel zurück oder None, wenn die Ergebnismenge leer ist.

Eine wiederverwendbare Paginierungsfunktion erstellen

In echten Anwendungen ist es praktisch, die Paginierungslogik in eine Funktion zu kapseln, damit der aufrufende Code übersichtlich bleibt:

Wiederverwendbarer paginate()-Helfer

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

Beachten Sie, dass Tabellennamen nicht als %s-Parameter übergeben werden können — der Connector unterstützt keine Parametrisierung von Bezeichnern. Die isidentifier()-Prüfung schützt vor Injection über das Tabellennamen-Argument.

Häufige Fallstricke

LIMIT ohne ORDER BY liefert unvorhersehbare Ergebnisse. MySQL garantiert keine stabile Zeilenreihenfolge, sofern Sie kein ORDER BY angeben. Zwei identische Abfragen können unterschiedliche Zeilen zurückgeben, wenn die Tabelle zwischen den Aufrufen geändert wird.

Große OFFSET-Werte sind langsam. LIMIT 10 OFFSET 1000000 veranlasst MySQL dennoch, eine Million Zeilen zu scannen und zu verwerfen, bevor zehn zurückgegeben werden. Für tiefe Paginierung bei sehr großen Tabellen sollten Sie Keyset-Paginierung (auch Cursor-basierte Paginierung genannt) in Betracht ziehen: Speichern Sie die letzte id der vorherigen Seite und verwenden Sie WHERE id > last_id LIMIT 10.

Bauen Sie LIMIT-Werte nicht durch String-Verkettung zusammen. Verwenden Sie %s-Platzhalter oder stellen Sie, wenn der Wert in Python berechnet wird, sicher, dass es sich um eine einfache ganze Zahl handelt, bevor Sie ihn in den SQL-String einbetten.

Zusammenfassung

ZielSQL-Muster
Erste N ZeilenSELECT ... LIMIT N
M Zeilen überspringen, N nehmenSELECT ... LIMIT N OFFSET M
Seite P mit Größe NLIMIT N OFFSET (P-1)*N
Nur eine ZeileSELECT ... LIMIT 1 + fetchone()
Geordnete erste NSELECT ... ORDER BY col LIMIT N

Verwandte Kapitel

Was this page helpful?