W3docs

MySQL Select en Python

Apprenez à utiliser SELECT en Python avec mysql-connector-python : récupérer toutes les lignes, une seule ligne, des colonnes spécifiques, fetchone vs fetchall.

L'instruction SELECT est la base de toute opération de lecture en base de données. En Python, vous l'exécutez via un objet cursor fourni par mysql-connector-python, puis vous récupérez les résultats avec fetchall(), fetchone() ou fetchmany(). Ce chapitre couvre les trois méthodes de récupération, la sélection de colonnes spécifiques, l'utilisation des noms de colonnes et les modèles de gestion des erreurs indispensables en code de production.

Prérequis

Installez le connecteur MySQL si ce n'est pas déjà fait :

pip install mysql-connector-python

Tous les exemples supposent :

  • Un serveur MySQL en cours d'exécution (local ou distant).
  • Une base de données appelée mydatabase avec une table customers comportant au moins les colonnes id, name et address.

Suivez Python MySQL Create Table pour créer la table, et Python MySQL Insert pour la remplir avec des exemples de lignes avant d'exécuter les exemples SELECT ci-dessous.

Connexion à la base de données

Chaque exemple commence par un objet de connexion. Plutôt que de répéter la configuration dans chaque extrait, conservez-la à un seul endroit et réutilisez-la :

import mysql.connector
from mysql.connector import Error

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

Remplacez yourusername et yourpassword par vos identifiants réels. Consultez Python MySQL Get Started pour savoir comment stocker les identifiants dans des variables d'environnement plutôt que de les coder en dur.

Sélectionner toutes les lignes avec fetchall()

fetchall() récupère toutes les lignes renvoyées par la requête et les stocke dans une liste Python de tuples. Utilisez-le lorsque le jeu de résultats est suffisamment petit pour tenir confortablement en mémoire.

Sélectionner tous les enregistrements de la table customers

import mysql.connector
from mysql.connector import Error

try:
    connection = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    cursor = connection.cursor()
    cursor.execute("SELECT * FROM customers")

    rows = cursor.fetchall()

    for row in rows:
        print(row)

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

Chaque row est un tuple dont les valeurs correspondent aux colonnes de la table dans l'ordre dans lequel elles apparaissent dans l'instruction CREATE TABLE. Pour une table customers avec les colonnes (id, name, address), vous obtiendriez une sortie similaire à :

(1, 'John', '123 Main St')
(2, 'Susan', '456 Oak Ave')
(3, 'Maria', '789 Pine Rd')

Pourquoi tout envelopper dans try/except/finally ?

Si une exception est levée entre l'ouverture de la connexion et sa fermeture, la connexion fuit — elle reste ouverte et consomme des ressources serveur jusqu'à ce que le serveur la ferme par expiration du délai. Le bloc finally garantit que cursor.close() et connection.close() sont toujours appelés, même en cas de problème.

Sélectionner une seule ligne avec fetchone()

Lorsque vous n'avez besoin que de la première ligne correspondante — ou que vous savez que la requête renvoie exactement un résultat — fetchone() est plus efficace que fetchall(). Il renvoie un seul tuple ou None s'il n'y a aucun résultat.

Récupérer une ligne de la table customers

import mysql.connector
from mysql.connector import Error

try:
    connection = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    cursor = connection.cursor()
    cursor.execute("SELECT * FROM customers")

    row = cursor.fetchone()

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

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

fetchone() fait avancer le pointeur interne du curseur. L'appeler à nouveau renvoie la ligne suivante. Cela le rend adapté à l'itération sur les résultats ligne par ligne sans charger l'intégralité du jeu de résultats en mémoire.

Sélectionner des colonnes spécifiques

L'utilisation de SELECT * renvoie toutes les colonnes de la table. Pour les tables volumineuses ou lorsque vous n'avez besoin que de quelques champs, nommez les colonnes explicitement. Cela réduit les données transférées sur le réseau et rend l'intention de votre code plus claire.

Sélectionner uniquement les colonnes name et address

import mysql.connector
from mysql.connector import Error

try:
    connection = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    cursor = connection.cursor()
    cursor.execute("SELECT name, address FROM customers")

    rows = cursor.fetchall()

    for row in rows:
        print(row)

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

Sortie (exemple) :

('John', '123 Main St')
('Susan', '456 Oak Ave')
('Maria', '789 Pine Rd')

Récupérer les lignes par lots avec fetchmany()

fetchmany(size) récupère size lignes à la fois. Utilisez-le lorsque le jeu de résultats est trop grand pour fetchall() mais que vous souhaitez tout de même traiter les lignes par blocs plutôt qu'une par une.

Traiter les résultats 10 lignes à la fois

import mysql.connector
from mysql.connector import Error

try:
    connection = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    cursor = connection.cursor()
    cursor.execute("SELECT * FROM customers")

    batch_size = 10
    while True:
        rows = cursor.fetchmany(batch_size)
        if not rows:
            break
        for row in rows:
            print(row)

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

fetchmany() renvoie une liste vide lorsqu'il n'y a plus de lignes, ce que la vérification if not rows: break détecte.

Accéder aux colonnes par nom avec un curseur dictionnaire

Par défaut, chaque ligne est un tuple simple. Si vous avez de nombreuses colonnes, accéder à row[4] au lieu de row["email"] rend le code difficile à lire et échoue silencieusement lorsque l'ordre des colonnes change. Passez dictionary=True au constructeur du curseur pour obtenir chaque ligne sous forme de dict à la place.

Utiliser un curseur dictionnaire pour accéder aux colonnes par nom

import mysql.connector
from mysql.connector import Error

try:
    connection = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    # dictionary=True makes each row a dict
    cursor = connection.cursor(dictionary=True)
    cursor.execute("SELECT * FROM customers")

    rows = cursor.fetchall()

    for row in rows:
        print(f"ID: {row['id']}, Name: {row['name']}, Address: {row['address']}")

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

Sortie :

ID: 1, Name: John, Address: 123 Main St
ID: 2, Name: Susan, Address: 456 Oak Ave

Les curseurs dictionnaire rendent le code auto-documenté et résistant aux réorganisations de colonnes.

Filtrer les lignes avec WHERE

Pour ne récupérer que les lignes correspondant à une condition, ajoutez une clause WHERE. Utilisez toujours des requêtes paramétrées — ne formatez jamais directement les valeurs fournies par l'utilisateur dans la chaîne SQL, car cela ouvre la porte aux attaques par injection SQL.

Récupérer les clients vivant dans une rue spécifique

import mysql.connector
from mysql.connector import Error

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

    sql = "SELECT * FROM customers WHERE address = %s"
    val = ("123 Main St",)  # Always pass a tuple, even for a single value
    cursor.execute(sql, val)

    rows = cursor.fetchall()

    for row in rows:
        print(row)

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

Le marqueur de position %s est renseigné par le pilote connecteur, qui échappe la valeur en toute sécurité. Consultez Python MySQL Where pour un traitement complet du filtrage, notamment les conditions multiples avec AND/OR.

Utiliser SELECT avec ORDER BY et LIMIT

Combinez SELECT avec ORDER BY pour trier les résultats et LIMIT pour limiter le nombre de lignes renvoyées. Ce modèle est essentiel pour afficher les enregistrements les plus récents ou implémenter la pagination.

Obtenir les 3 clients avec les IDs les plus élevés, triés du plus récent au plus ancien

import mysql.connector
from mysql.connector import Error

try:
    connection = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    cursor = connection.cursor()
    cursor.execute("SELECT * FROM customers ORDER BY id DESC LIMIT 3")

    rows = cursor.fetchall()

    for row in rows:
        print(row)

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

Pour un guide dédié au tri, consultez Python MySQL Order By. Pour la pagination avec OFFSET, consultez Python MySQL Limit.

Vérifier les noms de colonnes avec cursor.description

Après avoir appelé execute(), l'attribut description du curseur contient des métadonnées sur chaque colonne du résultat — y compris le nom de la colonne. C'est utile lorsque vous avez besoin des noms de colonnes de manière dynamique (par exemple, lors de la construction d'un export CSV) sans les coder en dur.

Afficher les noms de colonnes avec les données

import mysql.connector
from mysql.connector import Error

try:
    connection = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    cursor = connection.cursor()
    cursor.execute("SELECT * FROM customers")

    # cursor.description is a list of 7-item sequences; index 0 is the column name
    column_names = [desc[0] for desc in cursor.description]
    print("Columns:", column_names)

    rows = cursor.fetchall()
    for row in rows:
        print(dict(zip(column_names, row)))

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

Sortie (exemple) :

Columns: ['id', 'name', 'address']
{'id': 1, 'name': 'John', 'address': '123 Main St'}
{'id': 2, 'name': 'Susan', 'address': '456 Oak Ave'}

Choisir entre fetchall(), fetchone() et fetchmany()

MéthodeRenvoieIdéal pour
fetchall()Liste de tous les tuplesJeux de résultats petits à moyens où toutes les lignes sont nécessaires en même temps
fetchone()Un seul tuple ou NoneRecherche par clé primaire ; itération ligne par ligne
fetchmany(n)Liste d'au plus n tuplesGrands jeux de résultats traités en blocs en streaming

Si vous appelez fetchall() sur un jeu de résultats d'un million de lignes, Python stocke simultanément en mémoire le million de tuples. Pour les grandes tables, utilisez fetchmany() ou ajoutez une clause LIMIT à la requête.

Erreurs courantes et comment les corriger

ErreurCause probableCorrection
mysql.connector.errors.ProgrammingError: Table doesn't existLe nom de la table est incorrect ou la base de données n'a pas été sélectionnéeVérifiez le nom de la table ; assurez-vous que le paramètre database est défini dans connect()
mysql.connector.errors.InterfaceError: No result setAppel de fetchall() après une instruction non-SELECTN'appelez les méthodes fetch qu'après SELECT, SHOW ou d'autres instructions produisant un résultat
mysql.connector.errors.DatabaseError: Lost connectionDélai d'expiration réseau ou redémarrage du serveurRétablissez la connexion ; pour les applications longue durée, utilisez un pool de connexions
InternalError: Unread result foundDémarrage d'un nouvel execute() avant d'avoir consommé les résultats précédentsAppelez fetchall() ou cursor.reset() pour vider le jeu de résultats précédent

Résumé

  • Exécutez une instruction SELECT avec cursor.execute("SELECT ...").
  • Utilisez fetchall() pour les petits jeux de résultats, fetchone() pour une seule ligne et fetchmany(n) pour les grands ensembles de données traités par blocs.
  • Passez dictionary=True au curseur pour accéder aux colonnes par nom plutôt que par index.
  • Utilisez toujours des marqueurs paramétrés %s lors du filtrage avec des valeurs fournies par l'utilisateur.
  • Enveloppez toute opération de base de données dans try/except/finally pour garantir la fermeture de la connexion en cas d'erreur.

Chapitres associés

Was this page helpful?