Python MySQL DELETE – Eliminar filas de una tabla
Aprende a eliminar filas de una base de datos MySQL en Python con mysql-connector-python, usando consultas parametrizadas seguras, eliminaciones masivas y manejo de errores.
Eliminar registros de una base de datos MySQL es una tarea habitual en cualquier aplicación Python orientada a datos, ya sea para purgar sesiones expiradas, eliminar una cuenta de usuario o archivar pedidos antiguos. Este capítulo muestra cómo usar la instrucción SQL DELETE a través de la biblioteca mysql-connector-python, cubriendo eliminaciones de una sola fila, eliminaciones masivas, consultas parametrizadas seguras, transacciones y manejo de errores.
Requisitos previos
Necesitas lo siguiente antes de ejecutar los ejemplos:
- Python 3.8 o posterior instalado
mysql-connector-pythoninstalado (pip install mysql-connector-python)- Un servidor MySQL en ejecución (local o remoto)
- Una base de datos y una tabla con las que trabajar (consulta MySQL Get Started y MySQL Create Table)
Los ejemplos a continuación asumen que ya tienes una base de datos llamada mydatabase que contiene una tabla customers creada y poblada en el capítulo MySQL Insert.
La instrucción DELETE
La instrucción SQL DELETE elimina una o más filas de una tabla:
DELETE FROM table_name WHERE condition;Incluye siempre una cláusula WHERE. Sin ella, se eliminan todas las filas de la tabla. MySQL no te avisa — la tabla entera se borra al instante.
Conexión a MySQL
Antes de ejecutar cualquier instrucción debes abrir una conexión y crear un objeto cursor. El cursor es el objeto que envía SQL al servidor y recupera los resultados.
import mysql.connector
from mysql.connector import Error
mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
mycursor = mydb.cursor()Eliminar una sola fila
La forma más segura de apuntar a una fila específica es una consulta parametrizada. Pasa el valor como una tupla de Python — el conector sustituye el marcador %s después de escapar el valor, lo que previene la inyección SQL.
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 cuántas filas eliminó realmente la instrucción. Un valor de 0 significa que la condición WHERE no coincidió con nada — la consulta se ejecutó sin error, pero no se eliminó nada.
Por qué se requiere commit()
mysql-connector-python abre las conexiones en modo autocommit desactivado de forma predeterminada. Hasta que llames a mydb.commit(), la eliminación solo existe dentro de tu transacción actual y es invisible para otras conexiones. Si tu script falla antes de confirmar, la eliminación se revierte automáticamente. Llama a mydb.rollback() explícitamente en el bloque except para que la intención quede clara.
Eliminar varias filas con una sola instrucción
Si deseas eliminar todas las filas que coincidan con un patrón, mantén la cláusula WHERE pero amplía la condición. Solo se necesita una llamada 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()Eliminar filas por múltiples IDs (executemany)
Cuando tienes una lista de claves primarias que eliminar, usa executemany() para ejecutar la misma instrucción parametrizada una vez por elemento en un único viaje de ida y vuelta:
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() envuelve todas las eliminaciones individuales dentro de una única transacción, por lo que o todas tienen éxito o ninguna lo tiene.
Usar un gestor de contexto (patrón recomendado)
Abrir la conexión dentro de una instrucción with garantiza que siempre se cierre, incluso si se produce una excepción a mitad del proceso. Este es el patrón más limpio para el código en producción:
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}")El bloque with cierra tanto el cursor como la conexión cuando el bloque finaliza, independientemente de si se produjo una excepción.
Contar filas antes de eliminar (simulacro)
Antes de ejecutar un DELETE destructivo, es una buena práctica ejecutar primero un SELECT COUNT(*) con la misma cláusula WHERE. Esto actúa como un simulacro que te indica cuántas filas se verán afectadas:
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()Errores comunes
Olvidar la cláusula WHERE
# DANGER: deletes every row in the table
mycursor.execute("DELETE FROM customers")
mydb.commit()Verifica siempre que tu cláusula WHERE esté presente y sea correcta antes de llamar a commit().
Pasar una cadena en lugar de 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",))No llamar a commit()
mycursor.execute("DELETE FROM customers WHERE name = %s", ("John",))
# Missing mydb.commit() — the deletion will be silently rolled back
# when the connection closesBuenas prácticas
- Usa consultas parametrizadas (marcadores
%s) en todo momento. Nunca construyas cadenas SQL con f-strings o concatenación+usando datos suministrados por el usuario — esto abre una vulnerabilidad de inyección SQL. - Confirma o revierte siempre de forma explícita. Depender del cierre de la conexión para revertir una transacción es confuso; deja el resultado explícito en tu código.
- Comprueba
rowcountdespués de la eliminación para confirmar que se eliminó el número esperado de filas. - Usa transacciones para eliminaciones de varios pasos. Si necesitas eliminar filas de varias tablas relacionadas (por ejemplo, un pedido y sus líneas de detalle), envuelve las operaciones en una única transacción para no terminar con datos huérfanos.
- Agrega los índices adecuados en las columnas usadas en cláusulas
WHERE. Una eliminación que recorre toda la tabla es lenta con conjuntos de datos grandes.
Capítulos relacionados
- MySQL Get Started — instala el conector y crea tu primera conexión
- MySQL Create Table — crea las tablas de las que eliminarás filas
- MySQL Insert — agrega filas antes de practicar su eliminación
- MySQL Update — modifica filas en lugar de eliminarlas
- MySQL Where — domina la cláusula
WHEREusada en todas las instruccionesDELETE - MySQL Drop Table — elimina la estructura completa de una tabla, no solo sus filas