Python MySQL DELETE – Удаление строк из таблицы
Как удалять строки из MySQL в Python с помощью mysql-connector-python: параметризованные запросы, групповые удаления и обработка ошибок.
Удаление записей из базы данных MySQL — рутинная задача в любом Python-приложении, работающем с данными: будь то очистка устаревших сессий, удаление учётной записи пользователя или архивация старых заказов. В этой главе показано, как использовать SQL-оператор DELETE через библиотеку mysql-connector-python: удаление одной строки, групповые удаления, безопасные параметризованные запросы, транзакции и обработка ошибок.
Предварительные требования
Перед запуском примеров необходимо следующее:
- Python 3.8 или новее
- Установленный
mysql-connector-python(pip install mysql-connector-python) - Работающий сервер MySQL (локальный или удалённый)
- База данных и таблица для работы (см. MySQL Get Started и MySQL Create Table)
В примерах ниже предполагается, что у вас уже есть база данных mydatabase, содержащая таблицу customers, созданную и заполненную в главе MySQL Insert.
Оператор DELETE
SQL-оператор DELETE удаляет одну или несколько строк из таблицы:
DELETE FROM table_name WHERE condition;Всегда включайте условие WHERE. Без него будут удалены все строки таблицы. MySQL не предупреждает об этом — вся таблица будет очищена мгновенно.
Подключение к MySQL
Прежде чем выполнять любой оператор, необходимо открыть соединение и создать объект cursor. Cursor — это объект, который отправляет SQL на сервер и получает результаты.
import mysql.connector
from mysql.connector import Error
mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)
mycursor = mydb.cursor()Удаление одной строки
Самый надёжный способ нацелиться на конкретную строку — параметризованный запрос. Значение передаётся в виде кортежа Python — коннектор подставляет его вместо заполнителя %s после экранирования, что предотвращает 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 показывает, сколько строк фактически удалил оператор. Значение 0 означает, что условие WHERE не совпало ни с одной строкой — запрос выполнился без ошибки, но ничего удалено не было.
Зачем нужен commit()
mysql-connector-python открывает соединения в режиме autocommit off по умолчанию. Пока вы не вызовете mydb.commit(), удаление существует только внутри текущей транзакции и невидимо для других соединений. Если скрипт завершится аварийно до вызова commit, удаление автоматически откатится. Явно вызывайте mydb.rollback() в блоке except, чтобы намерение было понятным.
Удаление нескольких строк одним оператором
Если нужно удалить все строки, соответствующие шаблону, оставьте условие WHERE, расширив критерий. Потребуется только один вызов 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()Удаление строк по нескольким ID (executemany)
Если у вас есть список первичных ключей для удаления, используйте executemany(), чтобы выполнить один и тот же параметризованный оператор для каждого элемента за один обход:
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() оборачивает все отдельные удаления в одну транзакцию, так что либо все они выполнятся успешно, либо ни одно.
Использование контекстного менеджера (рекомендуемый паттерн)
Открытие соединения внутри оператора with гарантирует, что оно всегда будет закрыто, даже если в процессе возникнет исключение. Это наиболее чистый паттерн для производственного кода:
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}")Блок with закрывает и cursor, и соединение при выходе из блока, независимо от того, было ли возбуждено исключение.
Подсчёт строк перед удалением (пробный прогон)
Перед выполнением деструктивного DELETE рекомендуется сначала запустить SELECT COUNT(*) с тем же условием WHERE. Это играет роль пробного прогона, показывающего, сколько строк будет затронуто:
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()Распространённые ошибки
Забытое условие WHERE
# DANGER: deletes every row in the table
mycursor.execute("DELETE FROM customers")
mydb.commit()Всегда проверяйте, что условие WHERE присутствует и корректно, прежде чем вызывать commit().
Передача строки вместо кортежа
# 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",))Отсутствие вызова commit()
mycursor.execute("DELETE FROM customers WHERE name = %s", ("John",))
# Missing mydb.commit() — the deletion will be silently rolled back
# when the connection closesЛучшие практики
- Используйте параметризованные запросы (заполнители
%s) всегда. Никогда не формируйте SQL-строки через f-строки или конкатенацию+с пользовательскими данными — это открывает уязвимость для SQL-инъекции. - Всегда явно вызывайте commit или rollback. Полагаться на закрытие соединения для отката транзакции — запутанная практика; сделайте результат явным в своём коде.
- Проверяйте
rowcountпосле удаления, чтобы убедиться, что удалено ожидаемое число строк. - Используйте транзакции для многошаговых удалений. Если нужно удалить строки из нескольких связанных таблиц (например, заказ и его позиции), оберните операции в одну транзакцию, чтобы не получить осиротевшие данные.
- Добавляйте подходящие индексы для столбцов, используемых в условиях
WHERE. Удаление с полным сканированием таблицы работает медленно на больших объёмах данных.
Связанные главы
- MySQL Get Started — установка коннектора и создание первого соединения
- MySQL Create Table — создание таблиц, из которых вы будете удалять данные
- MySQL Insert — добавление строк перед практикой их удаления
- MySQL Update — изменение строк вместо их удаления
- MySQL Where — освоение условия
WHERE, используемого во всех операторахDELETE - MySQL Drop Table — удаление всей структуры таблицы, а не только её строк