W3docs

Python MySQL DELETE – Eliminare Righe da una Tabella

Scopri come eliminare righe da un database MySQL in Python con mysql-connector-python, query parametrizzate sicure, eliminazioni in blocco e gestione degli errori.

Rimuovere record da un database MySQL è un'operazione di routine in qualsiasi applicazione Python orientata ai dati — che tu stia eliminando sessioni scadute, rimuovendo un account utente o archiviando vecchi ordini. Questo capitolo mostra come usare l'istruzione SQL DELETE tramite la libreria mysql-connector-python, coprendo eliminazioni di singole righe, eliminazioni in blocco, query parametrizzate sicure, transazioni e gestione degli errori.

Prerequisiti

Prima di eseguire gli esempi sono necessari i seguenti elementi:

  • Python 3.8 o versione successiva installato
  • mysql-connector-python installato (pip install mysql-connector-python)
  • Un server MySQL in esecuzione (locale o remoto)
  • Un database e una tabella su cui lavorare (vedi MySQL Get Started e MySQL Create Table)

Gli esempi seguenti presuppongono che tu abbia già un database chiamato mydatabase contenente una tabella customers creata e popolata nel capitolo MySQL Insert.

L'istruzione DELETE

L'istruzione SQL DELETE rimuove una o più righe da una tabella:

DELETE FROM table_name WHERE condition;

Includi sempre una clausola WHERE. Senza di essa, ogni riga della tabella viene eliminata. MySQL non ti avvisa — l'intera tabella viene azzerata istantaneamente.

Connessione a MySQL

Prima di eseguire qualsiasi istruzione devi aprire una connessione e creare un oggetto cursore. Il cursore è l'oggetto che invia SQL al server e recupera i risultati.

import mysql.connector
from mysql.connector import Error

mydb = mysql.connector.connect(
    host="localhost",
    user="yourusername",
    password="yourpassword",
    database="mydatabase"
)

mycursor = mydb.cursor()

Eliminare una Singola Riga

Il modo più sicuro per individuare una riga specifica è una query parametrizzata. Passa il valore come tupla Python — il connettore sostituisce il segnaposto %s dopo aver eseguito l'escaping del valore, il che previene l'SQL injection.

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 = "DELETE FROM customers WHERE name = %s"
    val = ("John",)                   # note the trailing comma — this is a tuple

    mycursor.execute(sql, val)
    mydb.commit()                     # write the change to disk

    print(mycursor.rowcount, "record(s) deleted")

except Error as e:
    print(f"Error: {e}")
    mydb.rollback()                   # undo any partial changes on failure

finally:
    if mydb.is_connected():
        mycursor.close()
        mydb.close()

cursor.rowcount indica quante righe l'istruzione ha effettivamente rimosso. Un valore di 0 significa che la condizione WHERE non ha trovato corrispondenze — la query è stata eseguita senza errori, ma non è stata eliminata alcuna riga.

Perché commit() è obbligatorio

mysql-connector-python apre le connessioni in modalità autocommit off per impostazione predefinita. Fino a quando non chiami mydb.commit(), l'eliminazione esiste solo all'interno della transazione corrente ed è invisibile ad altre connessioni. Se lo script si blocca prima del commit, l'eliminazione viene automaticamente annullata. Chiama mydb.rollback() esplicitamente nel blocco except per rendere chiara l'intenzione.

Eliminare Più Righe con una Singola Istruzione

Se vuoi eliminare tutte le righe che corrispondono a un pattern, mantieni la clausola WHERE ma amplia la condizione. È necessaria una sola chiamata a execute().

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    # Delete every customer whose address contains "Highway"
    sql = "DELETE FROM customers WHERE address LIKE %s"
    val = ("%Highway%",)

    mycursor.execute(sql, val)
    mydb.commit()

    print(mycursor.rowcount, "record(s) deleted")

except Error as e:
    print(f"Error: {e}")
    mydb.rollback()

finally:
    if mydb.is_connected():
        mycursor.close()
        mydb.close()

Eliminare Righe per ID Multipli (executemany)

Quando hai un elenco di chiavi primarie da rimuovere, usa executemany() per eseguire la stessa istruzione parametrizzata una volta per ciascun elemento in un singolo round-trip:

import mysql.connector
from mysql.connector import Error

ids_to_delete = [(5,), (12,), (17,), (34,)]   # list of 1-tuples

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    sql = "DELETE FROM customers WHERE id = %s"
    mycursor.executemany(sql, ids_to_delete)
    mydb.commit()

    print(mycursor.rowcount, "record(s) deleted")

except Error as e:
    print(f"Error: {e}")
    mydb.rollback()

finally:
    if mydb.is_connected():
        mycursor.close()
        mydb.close()

executemany() racchiude tutte le singole eliminazioni all'interno di una singola transazione, quindi o tutte riescono o nessuna viene eseguita.

Utilizzo di un Context Manager (Pattern Consigliato)

Aprire la connessione all'interno di un'istruzione with garantisce che venga sempre chiusa, anche se si verifica un'eccezione a metà percorso. Questo è il pattern più pulito per il codice in produzione:

import mysql.connector
from mysql.connector import Error

db_config = {
    "host": "localhost",
    "user": "yourusername",
    "password": "yourpassword",
    "database": "mydatabase",
}

try:
    with mysql.connector.connect(**db_config) as mydb:
        with mydb.cursor() as mycursor:
            sql = "DELETE FROM customers WHERE name = %s"
            mycursor.execute(sql, ("Alice",))
            mydb.commit()
            print(mycursor.rowcount, "record(s) deleted")

except Error as e:
    print(f"Error: {e}")

Il blocco with chiude sia il cursore che la connessione all'uscita dal blocco, indipendentemente dal fatto che sia stata sollevata un'eccezione.

Contare le Righe Prima di Eliminare (Dry Run)

Prima di eseguire un DELETE distruttivo, è buona pratica eseguire prima un SELECT COUNT(*) con la stessa clausola WHERE. Questo funge da dry run che ti indica quante righe verranno interessate:

import mysql.connector
from mysql.connector import Error

try:
    mydb = mysql.connector.connect(
        host="localhost",
        user="yourusername",
        password="yourpassword",
        database="mydatabase"
    )
    mycursor = mydb.cursor()

    condition = "%Highway%"

    # Dry run: count matching rows first
    mycursor.execute("SELECT COUNT(*) FROM customers WHERE address LIKE %s", (condition,))
    count = mycursor.fetchone()[0]
    print(f"{count} row(s) would be deleted")

    if count > 0:
        mycursor.execute("DELETE FROM customers WHERE address LIKE %s", (condition,))
        mydb.commit()
        print(f"{mycursor.rowcount} row(s) deleted")

except Error as e:
    print(f"Error: {e}")
    mydb.rollback()

finally:
    if mydb.is_connected():
        mycursor.close()
        mydb.close()

Errori Comuni

Dimenticare la clausola WHERE

# DANGER: deletes every row in the table
mycursor.execute("DELETE FROM customers")
mydb.commit()

Verifica sempre che la clausola WHERE sia presente e corretta prima di chiamare commit().

Passare una stringa invece di una tupla

# Wrong — passes the string "John" character by character
mycursor.execute("DELETE FROM customers WHERE name = %s", "John")

# Correct — wrap the value in a tuple
mycursor.execute("DELETE FROM customers WHERE name = %s", ("John",))

Non chiamare commit()

mycursor.execute("DELETE FROM customers WHERE name = %s", ("John",))
# Missing mydb.commit() — the deletion will be silently rolled back
# when the connection closes

Best Practice

  • Usa query parametrizzate (segnaposti %s) in ogni momento. Non costruire mai stringhe SQL con f-string o concatenazione con + usando dati forniti dall'utente — questo apre una vulnerabilità di SQL injection.
  • Esegui sempre commit o rollback in modo esplicito. Affidarsi alla chiusura della connessione per annullare una transazione è fonte di confusione; rendi il risultato esplicito nel tuo codice.
  • Controlla rowcount dopo l'eliminazione per confermare che il numero atteso di righe sia stato rimosso.
  • Usa le transazioni per eliminazioni multi-step. Se devi eliminare righe da più tabelle correlate (ad es., un ordine e le sue voci), racchiudi le operazioni in una singola transazione per non ritrovarti mai con dati orfani.
  • Aggiungi indici appropriati sulle colonne usate nelle clausole WHERE. Un'eliminazione che scansiona l'intera tabella è lenta su dataset di grandi dimensioni.

Capitoli Correlati

  • MySQL Get Started — installa il connettore e crea la tua prima connessione
  • MySQL Create Table — crea le tabelle da cui eliminerai le righe
  • MySQL Insert — aggiungi righe prima di esercitarti a rimuoverle
  • MySQL Update — modifica le righe invece di rimuoverle
  • MySQL Where — padroneggia la clausola WHERE usata in tutte le istruzioni DELETE
  • MySQL Drop Table — rimuovi l'intera struttura di una tabella, non solo le sue righe
Was this page helpful?