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-pythonTous les exemples supposent :
- Un serveur MySQL en cours d'exécution (local ou distant).
- Une base de données appelée
mydatabaseavec une tablecustomerscomportant au moins les colonnesid,nameetaddress.
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 AveLes 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éthode | Renvoie | Idéal pour |
|---|---|---|
fetchall() | Liste de tous les tuples | Jeux de résultats petits à moyens où toutes les lignes sont nécessaires en même temps |
fetchone() | Un seul tuple ou None | Recherche par clé primaire ; itération ligne par ligne |
fetchmany(n) | Liste d'au plus n tuples | Grands 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
| Erreur | Cause probable | Correction |
|---|---|---|
mysql.connector.errors.ProgrammingError: Table doesn't exist | Le nom de la table est incorrect ou la base de données n'a pas été sélectionnée | Vérifiez le nom de la table ; assurez-vous que le paramètre database est défini dans connect() |
mysql.connector.errors.InterfaceError: No result set | Appel de fetchall() après une instruction non-SELECT | N'appelez les méthodes fetch qu'après SELECT, SHOW ou d'autres instructions produisant un résultat |
mysql.connector.errors.DatabaseError: Lost connection | Délai d'expiration réseau ou redémarrage du serveur | Rétablissez la connexion ; pour les applications longue durée, utilisez un pool de connexions |
InternalError: Unread result found | Démarrage d'un nouvel execute() avant d'avoir consommé les résultats précédents | Appelez fetchall() ou cursor.reset() pour vider le jeu de résultats précédent |
Résumé
- Exécutez une instruction
SELECTaveccursor.execute("SELECT ..."). - Utilisez
fetchall()pour les petits jeux de résultats,fetchone()pour une seule ligne etfetchmany(n)pour les grands ensembles de données traités par blocs. - Passez
dictionary=Trueau curseur pour accéder aux colonnes par nom plutôt que par index. - Utilisez toujours des marqueurs paramétrés
%slors du filtrage avec des valeurs fournies par l'utilisateur. - Enveloppez toute opération de base de données dans
try/except/finallypour garantir la fermeture de la connexion en cas d'erreur.
Chapitres associés
- Python MySQL Get Started — installer le pilote et établir une connexion
- Python MySQL Create Table — définir le schéma de table pour vos requêtes
- Python MySQL Insert — ajouter des lignes avant de les interroger
- Python MySQL Where — filtrer les résultats SELECT avec des conditions
- Python MySQL Order By — trier les résultats SELECT
- Python MySQL Limit — limiter le nombre de lignes renvoyées
- Python MySQL Join — combiner des données de plusieurs tables