W3docs

MySQL Where

Impara a usare la clausola WHERE di MySQL in Python con query parametrizzate, operatori di confronto, LIKE, IN, BETWEEN, controlli NULL e condizioni composte.

La clausola WHERE è il metodo principale per filtrare le righe in un'istruzione MySQL SELECT, UPDATE o DELETE. Questo capitolo mostra come utilizzarla da Python con mysql-connector-python, trattando filtri a singola condizione, operatori di confronto, LIKE, IN, BETWEEN, controlli NULL e logica composta AND/OR — il tutto usando query parametrizzate per prevenire l'iniezione SQL.

Prerequisiti

Assicurati di avere i seguenti elementi prima di eseguire gli esempi:

  • Python 3.x e un server MySQL in esecuzione.
  • mysql-connector-python installato:
pip install mysql-connector-python

Gli esempi assumono questa tabella e alcune righe di esempio:

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

Perché usare le query parametrizzate

Prima di qualsiasi esempio di codice, una regola fondamentale: non costruire mai una condizione WHERE concatenando direttamente stringhe fornite dall'utente nel tuo SQL. Questo schema è pericoloso:

# NEVER do this — SQL injection risk
name = input("Enter name: ")
sql = "SELECT * FROM customers WHERE name = '" + name + "'"

Se un utente inserisce ' OR '1'='1, la query restituisce ogni riga. Al contrario, passa sempre i valori attraverso l'interfaccia parametrizzata di mysql-connector-python:

sql = "SELECT * FROM customers WHERE name = %s"
mycursor.execute(sql, (name,))

Il connettore esegue l'escape del valore in modo sicuro prima che raggiunga il database. Il segnaposto è sempre %s indipendentemente dal tipo di dati della colonna (intero, string, data e così via).

Filtrare per un valore esatto

Il caso d'uso più comune: recuperare righe in cui una colonna è uguale a un valore specifico.

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

Output di esempio:

(1, 'Alice', 'Oak Avenue 1', 30)

Nota che val deve essere una tupla anche quando c'è un solo valore — da qui la virgola finale in ("Alice",).

Operatori di confronto

La clausola WHERE supporta tutti gli operatori di confronto SQL standard:

OperatoreSignificatoCondizione di esempio
=Ugualeage = 30
<> o !=Diversoage <> 30
>Maggiore diage > 25
>=Maggiore o ugualeage >= 28
<Minore diage < 30
<=Minore o ugualeage <= 30

Esempio: righe dove l'età è maggiore di 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()

Output di esempio:

('Alice', 30)
('Charlie', 35)

Corrispondenza con caratteri jolly tramite LIKE

LIKE confronta pattern all'interno di colonne string. Sono disponibili due caratteri jolly:

  • % — corrisponde a zero o più caratteri.
  • _ — corrisponde esattamente a un carattere.
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()

Output di esempio:

('Alice', 'Oak Avenue 1')
('Diana', 'Oak Avenue 3')

LIKE non distingue tra maiuscole e minuscole sulle colonne utf8mb4 per impostazione predefinita. Usa LIKE BINARY se hai bisogno di una corrispondenza con distinzione tra maiuscole e minuscole.

Corrispondenza di più valori con IN

IN verifica se il valore di una colonna compare in un elenco. È equivalente a concatenare più condizioni OR ma molto più leggibile.

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

Output di esempio:

('Alice', 30)
('Charlie', 35)
('Eve', 22)

Poiché il numero di valori IN può variare in fase di esecuzione, lo schema sopra costruisce la string dei segnaposto dinamicamente (", ".join(["%s"] * len(names))). Questo mantiene la parametrizzazione intatta indipendentemente dalla lunghezza dell'elenco.

Filtraggio per intervallo con BETWEEN

BETWEEN seleziona le righe in cui il valore di una colonna rientra in un intervallo inclusivo:

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

Output di esempio:

('Alice', 30)
('Bob', 25)
('Diana', 28)

BETWEEN 25 AND 30 include entrambi i valori degli estremi (25 e 30). Funziona con date e stringhe oltre che con i numeri.

Verifica dei valori NULL

Un valore NULL significa che il campo non contiene dati. Non puoi verificare la presenza di NULL con = — devi usare IS NULL o 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()

Output di esempio:

('Eve',)

IS NULL e IS NOT NULL non richiedono parametri, quindi nessun secondo argomento viene passato a execute().

Condizioni composte con AND e OR

Combina più condizioni in una clausola WHERE usando AND (tutte le condizioni devono essere vere) e OR (almeno una condizione deve essere vera).

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

Output di esempio:

('Alice', 'Oak Avenue 1', 30)

Diana abita in Oak Avenue ma ha 28 anni, quindi non soddisfa la condizione age > 28.

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

Output di esempio:

('Alice', 30)
('Eve', 22)

Usa le parentesi per controllare la precedenza quando mescoli AND e OR: (a OR b) AND c si comporta diversamente da a OR (b AND c).

Usare WHERE con UPDATE e DELETE

La clausola WHERE è altrettanto importante nelle istruzioni UPDATE e DELETE. Senza di essa, l'istruzione interessa ogni riga della tabella.

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

Output di esempio:

1 row(s) updated

Verifica sempre la tua condizione WHERE con un SELECT prima di eseguire un UPDATE o un DELETE. Una condizione mancante o errata su una tabella di produzione può essere difficile da annullare. Consulta MySQL Update e MySQL Delete per maggiori dettagli.

Recuperare una riga o tutte le righe

Dopo execute(), scegli quante righe recuperare:

MetodoRestituisceUsa quando
fetchone()La prima riga corrispondente (o None)Aspetti al massimo un risultato, ad esempio ricerca per chiave primaria
fetchmany(n)Fino a n righePaginazione o anteprime limitate
fetchall()Tutte le righe corrispondenti come listaSet di risultati piccoli in cui caricare tutte le righe contemporaneamente va bene
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)

Per set di risultati di grandi dimensioni, preferisci fetchmany() in un ciclo oppure usa un cursore lato server (MySQLCursorBuffered) per evitare di caricare tutte le righe in memoria in una volta sola.

Errori comuni da evitare

Usare = per verificare NULL. WHERE address = NULL non restituisce mai righe; usa sempre IS NULL.

Dimenticare la virgola finale in una tupla a valore singolo. Scrivere val = ("Alice") crea una string, non una tupla. Scrivi val = ("Alice",).

Formattare i valori direttamente nell'SQL. Le f-string e la formattazione con % bypassano la parametrizzazione. Passa i valori come secondo argomento a execute().

Omettere WHERE in UPDATE o DELETE. Senza una clausola WHERE, ogni riga della tabella viene interessata.

Usare Python None dove SQL NULL è necessario. mysql-connector-python mappa automaticamente Python None a SQL NULL, quindi mycursor.execute("UPDATE customers SET address = %s WHERE id = %s", (None, 1)) imposta address a NULL correttamente.

Cosa fare dopo

  • MySQL Order By — ordina le righe restituite dalla clausola WHERE.
  • MySQL Limit — limita il numero di righe restituite.
  • MySQL Update — modifica le righe che soddisfano una condizione.
  • MySQL Delete — elimina le righe che soddisfano una condizione.
  • MySQL Join — filtra su più tabelle combinando WHERE con i join.
Was this page helpful?