W3docs

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-python installé :
pip install mysql-connector-python

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érateurSignificationExemple de condition
=Égalage = 30
<> ou !=Différentage <> 30
>Supérieur àage > 25
>=Supérieur ou égalage >= 28
<Inférieur àage < 30
<=Inférieur ou égalage <= 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) updated

Vé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éthodeRetourneUtiliser 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 lignesPagination ou aperçus limités
fetchall()Toutes les lignes correspondantes sous forme de listePetits 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 WHERE combiné aux jointures.
Was this page helpful?