MySQL Select in Python
Impara a usare SELECT in Python con mysql-connector-python: recupera righe, usa fetchone e fetchall, filtra e ordina i dati.
L'istruzione SELECT è la base di ogni operazione di lettura su database. In Python viene eseguita tramite un oggetto cursor fornito da mysql-connector-python, e i risultati vengono recuperati con fetchall(), fetchone() o fetchmany(). Questo capitolo copre tutti e tre i metodi di fetch, come selezionare colonne specifiche, come lavorare con i nomi delle colonne e i pattern di gestione degli errori necessari nel codice in produzione.
Prerequisiti
Installa il connettore MySQL se non lo hai ancora fatto:
pip install mysql-connector-pythonTutti gli esempi presuppongono:
- Un server MySQL in esecuzione (locale o remoto).
- Un database chiamato
mydatabasecon una tabellacustomersche ha almeno le colonneid,nameeaddress.
Segui Python MySQL Create Table per creare la tabella e Python MySQL Insert per popolarla con righe di esempio prima di eseguire gli esempi SELECT qui sotto.
Connessione al database
Ogni esempio parte da un oggetto di connessione. Invece di ripetere la configurazione in ogni snippet, tienila in un unico posto e riutilizzala:
import mysql.connector
from mysql.connector import Error
connection = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)Sostituisci yourusername e yourpassword con le tue credenziali effettive. Consulta Python MySQL Get Started per scoprire come memorizzare le credenziali nelle variabili d'ambiente anziché inserirle direttamente nel codice.
Selezionare tutte le righe con fetchall()
fetchall() recupera ogni riga restituita dalla query e le memorizza in una lista Python di tuple. Usala quando il set di risultati è abbastanza piccolo da stare comodamente in memoria.
Seleziona tutti i record dalla tabella 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()Ogni row è una tupla i cui valori corrispondono alle colonne della tabella nell'ordine in cui appaiono nell'istruzione CREATE TABLE. Per una tabella customers con colonne (id, name, address) si otterrà un output simile a:
(1, 'John', '123 Main St')
(2, 'Susan', '456 Oak Ave')
(3, 'Maria', '789 Pine Rd')Perché racchiudere tutto in try/except/finally?
Se viene sollevata un'eccezione tra l'apertura e la chiusura della connessione, la connessione rimane aperta e consuma risorse del server finché il server non la chiude per timeout. Il blocco finally garantisce che cursor.close() e connection.close() vengano sempre chiamati, anche quando qualcosa va storto.
Selezionare una singola riga con fetchone()
Quando hai bisogno solo della prima riga corrispondente — o sai che la query restituisce esattamente un risultato — fetchone() è più efficiente di fetchall(). Restituisce una singola tupla oppure None se non ci sono risultati.
Recupera una riga dalla tabella 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() avanza il puntatore interno del cursore. Chiamarla di nuovo restituisce la riga successiva. Questo la rende adatta per iterare sui risultati una riga alla volta senza caricare l'intero set di risultati in memoria.
Selezionare colonne specifiche
Usare SELECT * restituisce ogni colonna della tabella. Per tabelle grandi o quando hai bisogno solo di alcuni campi, specifica esplicitamente i nomi delle colonne. Questo riduce i dati trasferiti sulla rete e rende chiara l'intenzione del codice.
Seleziona solo le colonne name e 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()Output (esempio):
('John', '123 Main St')
('Susan', '456 Oak Ave')
('Maria', '789 Pine Rd')Recuperare righe in batch con fetchmany()
fetchmany(size) recupera size righe alla volta. Usala quando il set di risultati è troppo grande per fetchall() ma vuoi comunque elaborare le righe in blocchi anziché una per una.
Elabora i risultati 10 righe alla volta
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() restituisce una lista vuota quando non ci sono più righe, che è ciò che il controllo if not rows: break rileva.
Accedere alle colonne per nome con un cursore dizionario
Per impostazione predefinita, ogni riga è una tupla semplice. Se hai molte colonne, accedere a row[4] invece di row["email"] rende il codice difficile da leggere e si rompe silenziosamente quando l'ordine delle colonne cambia. Passa dictionary=True al costruttore del cursore per ottenere ogni riga come dict invece.
Usa un cursore dizionario per l'accesso alle colonne per nome
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()Output:
ID: 1, Name: John, Address: 123 Main St
ID: 2, Name: Susan, Address: 456 Oak AveI cursori dizionario rendono il codice auto-documentante e resistente al riordinamento delle colonne.
Filtrare le righe con WHERE
Per recuperare solo le righe che corrispondono a una condizione, aggiungi una clausola WHERE. Usa sempre query parametrizzate — non formattare mai i valori forniti dall'utente direttamente nella stringa SQL, perché ciò apre la porta agli attacchi di SQL injection.
Recupera i clienti che vivono in una via specifica
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()Il segnaposto %s viene sostituito dal driver del connettore, che esegue l'escape del valore in modo sicuro. Consulta Python MySQL Where per un trattamento completo del filtraggio, incluse condizioni multiple con AND/OR.
Usare SELECT con ORDER BY e LIMIT
Combina SELECT con ORDER BY per ordinare i risultati e LIMIT per limitare il numero di righe restituite. Questo schema è essenziale per visualizzare i record più recenti o implementare la paginazione.
Ottieni i 3 clienti con gli ID più alti, ordinati dal più recente
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()Per una guida dedicata all'ordinamento, consulta Python MySQL Order By. Per la paginazione con OFFSET, consulta Python MySQL Limit.
Verificare i nomi delle colonne con cursor.description
Dopo aver chiamato execute(), l'attributo description del cursore contiene metadati su ogni colonna del risultato — incluso il nome della colonna. Questo è utile quando hai bisogno dei nomi delle colonne in modo dinamico (ad esempio, durante la creazione di un'esportazione CSV) senza inserirli direttamente nel codice.
Stampa i nomi delle colonne insieme ai dati
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()Output (esempio):
Columns: ['id', 'name', 'address']
{'id': 1, 'name': 'John', 'address': '123 Main St'}
{'id': 2, 'name': 'Susan', 'address': '456 Oak Ave'}Scegliere tra fetchall(), fetchone() e fetchmany()
| Metodo | Restituisce | Ideale per |
|---|---|---|
fetchall() | Lista di tutte le tuple | Set di risultati piccoli o medi dove tutte le righe sono necessarie subito |
fetchone() | Singola tupla o None | Ricerca per chiave primaria; iterazione riga per riga |
fetchmany(n) | Lista di massimo n tuple | Set di risultati grandi elaborati in blocchi in streaming |
Se chiami fetchall() su un set di risultati di un milione di righe, Python memorizza tutte le tuple in memoria contemporaneamente. Per tabelle grandi, usa fetchmany() oppure aggiungi una clausola LIMIT alla query.
Errori comuni e come risolverli
| Errore | Causa probabile | Soluzione |
|---|---|---|
mysql.connector.errors.ProgrammingError: Table doesn't exist | Il nome della tabella è errato o il database non è stato selezionato | Controlla il nome della tabella; assicurati che il parametro database sia impostato su connect() |
mysql.connector.errors.InterfaceError: No result set | Chiamata a fetchall() dopo un'istruzione non-SELECT | Chiama i metodi fetch solo dopo SELECT, SHOW o altre istruzioni che producono risultati |
mysql.connector.errors.DatabaseError: Lost connection | Timeout di rete o riavvio del server | Ristabilisci la connessione; per applicazioni a lunga esecuzione, usa un pool di connessioni |
InternalError: Unread result found | Avvio di un nuovo execute() prima di consumare i risultati precedenti | Chiama fetchall() o cursor.reset() per svuotare il set di risultati precedente |
Riepilogo
- Esegui un'istruzione
SELECTconcursor.execute("SELECT ..."). - Usa
fetchall()per set di risultati piccoli,fetchone()per una singola riga efetchmany(n)per dataset grandi elaborati in blocchi. - Passa
dictionary=Trueal cursore per accedere alle colonne per nome anziché per indice. - Usa sempre i segnaposto parametrizzati
%squando filtri con valori forniti dall'utente. - Racchiudi ogni operazione sul database in
try/except/finallyper garantire che la connessione venga chiusa in caso di errore.
Capitoli correlati
- Python MySQL Get Started — installa il driver e stabilisci una connessione
- Python MySQL Create Table — definisci lo schema della tabella per le tue query
- Python MySQL Insert — aggiungi righe prima di interrogarle
- Python MySQL Where — filtra i risultati SELECT con condizioni
- Python MySQL Order By — ordina i risultati SELECT
- Python MySQL Limit — limita il numero di righe restituite
- Python MySQL Join — combina dati da più tabelle