MySQL Where
Apprenez à utiliser la clause WHERE de MySQL en Python avec des requêtes paramétrées, les opérateurs de comparaison, LIKE, IN, BETWEEN, NULL et les conditions composées.
La clause WHERE est le principal moyen de filtrer des lignes dans une instruction MySQL SELECT, UPDATE ou DELETE. Ce chapitre montre comment l'utiliser depuis Python avec mysql-connector-python, en couvrant les filtres à condition unique, les opérateurs de comparaison, LIKE, IN, BETWEEN, les vérifications de NULL, et la logique composée AND/OR — le tout en utilisant des requêtes paramétrées pour prévenir l'injection SQL.
Prérequis
Assurez-vous d'avoir les éléments suivants en place avant d'exécuter les exemples :
- Python 3.x et un serveur MySQL en cours d'exécution.
mysql-connector-pythoninstallé :
pip install mysql-connector-python- Une base de données avec une table
customersdéjà créée — consultez MySQL Create Database et MySQL Create Table si vous ne les avez pas encore configurées.
Les exemples supposent l'existence de cette table et de quelques lignes d'exemple :
CREATE TABLE IF NOT EXISTS customers (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
address VARCHAR(255),
age INT
);
INSERT INTO customers (name, address, age) VALUES
('Alice', 'Oak Avenue 1', 30),
('Bob', 'Pine Street 42', 25),
('Charlie', 'Maple Road 7', 35),
('Diana', 'Oak Avenue 3', 28),
('Eve', NULL, 22);Pourquoi utiliser des requêtes paramétrées
Avant tout exemple de code, une règle : ne jamais construire une condition WHERE en concaténant directement des chaînes fournies par l'utilisateur dans votre SQL. Ce modèle est dangereux :
# NEVER do this — SQL injection risk
name = input("Enter name: ")
sql = "SELECT * FROM customers WHERE name = '" + name + "'"Si un utilisateur saisit ' OR '1'='1, la requête retourne toutes les lignes. À la place, passez toujours les valeurs via l'interface paramétrée de mysql-connector-python :
sql = "SELECT * FROM customers WHERE name = %s"
mycursor.execute(sql, (name,))Le connecteur échappe la valeur de manière sécurisée avant qu'elle n'atteigne la base de données. L'espace réservé est toujours %s quel que soit le type de données de la colonne (entier, string, date, etc.).
Filtrer par une valeur exacte
Le cas d'usage le plus courant : récupérer les lignes où une colonne est égale à une valeur spécifique.
import mysql.connector
from mysql.connector import Error
try:
mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
mycursor = mydb.cursor()
sql = "SELECT * FROM customers WHERE name = %s"
val = ("Alice",)
mycursor.execute(sql, val)
results = mycursor.fetchall()
for row in results:
print(row)
except Error as e:
print(f"Error: {e}")
finally:
if mydb.is_connected():
mycursor.close()
mydb.close()Exemple de sortie :
(1, 'Alice', 'Oak Avenue 1', 30)Notez que val doit être un tuple même lorsqu'il n'y a qu'une seule valeur — d'où la virgule finale dans ("Alice",).
Opérateurs de comparaison
La clause WHERE prend en charge tous les opérateurs de comparaison SQL standard :
| Opérateur | Signification | Exemple de condition |
|---|---|---|
= | Égal | age = 30 |
<> ou != | Différent | age <> 30 |
> | Supérieur à | age > 25 |
>= | Supérieur ou égal | age >= 28 |
< | Inférieur à | age < 30 |
<= | Inférieur ou égal | age <= 30 |
Exemple : Lignes où l'âge est supérieur à 28
import mysql.connector
from mysql.connector import Error
try:
mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
mycursor = mydb.cursor()
sql = "SELECT name, age FROM customers WHERE age > %s"
val = (28,)
mycursor.execute(sql, val)
for row in mycursor.fetchall():
print(row)
except Error as e:
print(f"Error: {e}")
finally:
if mydb.is_connected():
mycursor.close()
mydb.close()Exemple de sortie :
('Alice', 30)
('Charlie', 35)Correspondance par jokers avec LIKE
LIKE correspond à des motifs dans des colonnes de type string. Deux caractères jokers sont disponibles :
%— correspond à zéro ou plusieurs caractères._— correspond à exactement un caractère.
import mysql.connector
from mysql.connector import Error
try:
mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
mycursor = mydb.cursor()
# Find customers whose address starts with "Oak"
sql = "SELECT name, address FROM customers WHERE address LIKE %s"
val = ("Oak%",)
mycursor.execute(sql, val)
for row in mycursor.fetchall():
print(row)
except Error as e:
print(f"Error: {e}")
finally:
if mydb.is_connected():
mycursor.close()
mydb.close()Exemple de sortie :
('Alice', 'Oak Avenue 1')
('Diana', 'Oak Avenue 3')LIKE est insensible à la casse sur les colonnes utf8mb4 par défaut. Utilisez LIKE BINARY si vous avez besoin d'une correspondance sensible à la casse.
Correspondance de plusieurs valeurs avec IN
IN teste si la valeur d'une colonne figure dans une liste. C'est équivalent à enchaîner plusieurs conditions OR mais bien plus lisible.
import mysql.connector
from mysql.connector import Error
try:
mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
mycursor = mydb.cursor()
names = ("Alice", "Charlie", "Eve")
# Build one %s placeholder per value
placeholders = ", ".join(["%s"] * len(names))
sql = f"SELECT name, age FROM customers WHERE name IN ({placeholders})"
mycursor.execute(sql, names)
for row in mycursor.fetchall():
print(row)
except Error as e:
print(f"Error: {e}")
finally:
if mydb.is_connected():
mycursor.close()
mydb.close()Exemple de sortie :
('Alice', 30)
('Charlie', 35)
('Eve', 22)Comme le nombre de valeurs IN peut varier à l'exécution, le modèle ci-dessus construit la chaîne d'espaces réservés de manière dynamique (", ".join(["%s"] * len(names))). Cela maintient la paramétrisation intacte quelle que soit la longueur de la liste.
Filtrage par plage avec BETWEEN
BETWEEN sélectionne les lignes dont la valeur d'une colonne se situe dans une plage inclusive :
import mysql.connector
from mysql.connector import Error
try:
mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
mycursor = mydb.cursor()
sql = "SELECT name, age FROM customers WHERE age BETWEEN %s AND %s"
val = (25, 30)
mycursor.execute(sql, val)
for row in mycursor.fetchall():
print(row)
except Error as e:
print(f"Error: {e}")
finally:
if mydb.is_connected():
mycursor.close()
mydb.close()Exemple de sortie :
('Alice', 30)
('Bob', 25)
('Diana', 28)BETWEEN 25 AND 30 inclut les deux valeurs aux extrémités (25 et 30). Cela fonctionne également avec des dates et des strings, pas seulement des nombres.
Vérification des valeurs NULL
Une valeur NULL signifie que le champ ne contient aucune donnée. Vous ne pouvez pas tester NULL avec = — vous devez utiliser IS NULL ou IS NOT NULL.
import mysql.connector
from mysql.connector import Error
try:
mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
mycursor = mydb.cursor()
# Find customers with no address recorded
sql = "SELECT name FROM customers WHERE address IS NULL"
mycursor.execute(sql)
for row in mycursor.fetchall():
print(row)
except Error as e:
print(f"Error: {e}")
finally:
if mydb.is_connected():
mycursor.close()
mydb.close()Exemple de sortie :
('Eve',)IS NULL et IS NOT NULL ne prennent aucun paramètre, donc aucun deuxième argument n'est passé à execute().
Conditions composées avec AND et OR
Combinez plusieurs conditions dans une clause WHERE en utilisant AND (toutes les conditions doivent être vraies) et OR (au moins une condition doit être vraie).
Exemple avec AND
import mysql.connector
from mysql.connector import Error
try:
mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
mycursor = mydb.cursor()
# Customers on "Oak Avenue" who are older than 28
sql = "SELECT name, address, age FROM customers WHERE address LIKE %s AND age > %s"
val = ("Oak%", 28)
mycursor.execute(sql, val)
for row in mycursor.fetchall():
print(row)
except Error as e:
print(f"Error: {e}")
finally:
if mydb.is_connected():
mycursor.close()
mydb.close()Exemple de sortie :
('Alice', 'Oak Avenue 1', 30)Diana habite sur Oak Avenue mais a 28 ans, donc elle ne satisfait pas la condition age > 28.
Exemple avec OR
import mysql.connector
from mysql.connector import Error
try:
mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
mycursor = mydb.cursor()
# Customers named Alice OR younger than 25
sql = "SELECT name, age FROM customers WHERE name = %s OR age < %s"
val = ("Alice", 25)
mycursor.execute(sql, val)
for row in mycursor.fetchall():
print(row)
except Error as e:
print(f"Error: {e}")
finally:
if mydb.is_connected():
mycursor.close()
mydb.close()Exemple de sortie :
('Alice', 30)
('Eve', 22)Utilisez des parenthèses pour contrôler la priorité lorsque vous mélangez AND et OR : (a OR b) AND c se comporte différemment de a OR (b AND c).
Utiliser WHERE avec UPDATE et DELETE
La clause WHERE est tout aussi indispensable dans les instructions UPDATE et DELETE. Sans elle, l'instruction affecte toutes les lignes de la table.
import mysql.connector
from mysql.connector import Error
try:
mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
mycursor = mydb.cursor()
# Update only Alice's address
sql = "UPDATE customers SET address = %s WHERE name = %s"
val = ("New Street 10", "Alice")
mycursor.execute(sql, val)
mydb.commit()
print(mycursor.rowcount, "row(s) updated")
except Error as e:
print(f"Error: {e}")
mydb.rollback()
finally:
if mydb.is_connected():
mycursor.close()
mydb.close()Exemple de sortie :
1 row(s) updatedVérifiez toujours votre condition WHERE avec un SELECT avant d'exécuter un UPDATE ou un DELETE. Une condition manquante ou incorrecte sur une table de production peut être difficile à annuler. Consultez MySQL Update et MySQL Delete pour plus de détails.
Récupérer une seule ligne ou toutes les lignes
Après execute(), choisissez le nombre de lignes à récupérer :
| Méthode | Retourne | Utiliser quand |
|---|---|---|
fetchone() | La première ligne correspondante (ou None) | Vous attendez au plus un résultat, par ex. recherche par clé primaire |
fetchmany(n) | Jusqu'à n lignes | Pagination ou aperçus limités |
fetchall() | Toutes les lignes correspondantes sous forme de liste | Petits ensembles de résultats où charger toutes les lignes en une fois est acceptable |
mycursor.execute("SELECT * FROM customers WHERE age > %s", (25,))
# Fetch only the first result
first = mycursor.fetchone()
print(first) # (1, 'Alice', 'Oak Avenue 1', 30)Pour les grands ensembles de résultats, préférez fetchmany() dans une boucle ou utilisez un curseur côté serveur (MySQLCursorBuffered) pour éviter de charger toutes les lignes en mémoire en une seule fois.
Erreurs courantes à éviter
Utiliser = pour vérifier NULL. WHERE address = NULL ne retourne jamais de lignes ; utilisez toujours IS NULL.
Oublier la virgule finale dans un tuple à une seule valeur. Écrire val = ("Alice") crée une string, pas un tuple. Écrivez val = ("Alice",).
Formater des valeurs dans le SQL avec des chaînes. Les f-strings et le formatage % contournent la paramétrisation. Passez les valeurs comme deuxième argument à execute().
Omettre WHERE dans UPDATE ou DELETE. Sans clause WHERE, toutes les lignes de la table sont affectées.
Utiliser Python None là où SQL NULL est nécessaire. mysql-connector-python mappe automatiquement Python None vers SQL NULL, donc mycursor.execute("UPDATE customers SET address = %s WHERE id = %s", (None, 1)) définit address à NULL correctement.
Prochaines étapes
- MySQL Order By — trier les lignes retournées par votre clause
WHERE. - MySQL Limit — limiter le nombre de lignes retournées.
- MySQL Update — modifier les lignes correspondant à une condition.
- MySQL Delete — supprimer les lignes correspondant à une condition.
- MySQL Join — filtrer sur plusieurs tables avec
WHEREcombiné aux jointures.