Урок 80. MySQL и Python
⚡ Кратко: решения
К каждому заданию приведён рабочий код. Обращай внимание на:
- запятую в кортеже из одного значения
(value,); connection.commit()для изменяющих данных запросов;- параметризованные запросы вместо f-string;
withи обработку исключений в финальных решениях.
✅ Решения заданий
Задание 1. Подключение и список отделов
Файл: task01_departments.py
import pymysql
config = {
"host": "localhost",
"user": "root",
"password": "yourpassword",
"database": "hr",
"charset": "utf8mb4",
}
connection = pymysql.connect(**config)
cursor = connection.cursor()
cursor.execute("SELECT department_id, department_name FROM departments")
for department_id, department_name in cursor:
print(f"{department_id}: {department_name}")
cursor.close()
connection.close()
Пояснение: создаём соединение и курсор, выполняем SELECT, итерируемся по строкам и печатаем результат. В конце закрываем курсор и соединение.
Задание 2. Параметризованный SELECT
Файл: task02_param_select.py
import pymysql
config = {
"host": "localhost",
"user": "root",
"password": "yourpassword",
"database": "hr",
"charset": "utf8mb4",
}
department_id = 50
connection = pymysql.connect(**config)
try:
cursor = connection.cursor()
cursor.execute(
"SELECT first_name, last_name FROM employees WHERE department_id = %s",
(department_id,)
)
for first_name, last_name in cursor:
print(f"{first_name} {last_name}")
finally:
cursor.close()
connection.close()
Пояснение: значение department_id передаётся вторым аргументом в виде кортежа. Плейсхолдер %s заменяется безопасно.
Задание 3. Добавление нового отдела
Файл: task03_insert.py
import pymysql
config = {
"host": "localhost",
"user": "root",
"password": "yourpassword",
"database": "hr",
"charset": "utf8mb4",
}
connection = pymysql.connect(**config)
try:
cursor = connection.cursor()
cursor.execute(
"INSERT INTO departments (department_name, location_id) VALUES (%s, %s)",
("Data Science", 1700)
)
connection.commit()
print("Добавлено строк:", cursor.rowcount)
finally:
cursor.close()
connection.close()
Пояснение: для сохранения изменений в базе обязателен connection.commit(). cursor.rowcount показывает, сколько строк было затронуто.
Задание 4. Безопасный запрос по вводу пользователя
Файл: task04_safe_input.py
import pymysql
config = {
"host": "localhost",
"user": "root",
"password": "yourpassword",
"database": "hr",
"charset": "utf8mb4",
}
user_input = input("Введите department_id: ")
connection = pymysql.connect(**config)
try:
cursor = connection.cursor()
cursor.execute(
"SELECT department_name FROM departments WHERE department_id = %s",
(user_input,)
)
row = cursor.fetchone()
if row:
print("Название отдела:", row[0])
else:
print("Отдел не найден")
finally:
cursor.close()
connection.close()
Пояснение: даже если пользователь введёт 1 OR 1=1, библиотека воспримет это как одно строковое значение. SQL-инъекция невозможна.
Задание 5. Рефакторинг на with и обработку ошибок
Файл: task05_with_errors.py
import pymysql
config = {
"host": "localhost",
"user": "root",
"password": "yourpassword",
"database": "hr",
"charset": "utf8mb4",
}
try:
with pymysql.connect(**config) as connection:
with connection.cursor() as cursor:
cursor.execute("SELECT department_id, department_name FROM departments")
for department_id, department_name in cursor:
print(f"{department_id}: {department_name}")
except pymysql.MySQLError as e:
print("Ошибка при работе с базой данных:", e)
Пояснение: with закрывает соединение и курсор автоматически, а except перехватывает ошибки MySQL, чтобы программа не падала.
Задание 6. Подготовка к домашнему заданию: список стран
Файл: task06_countries.py
import pymysql
config = {
"host": "localhost",
"user": "root",
"password": "yourpassword",
"database": "world",
"charset": "utf8mb4",
}
with pymysql.connect(**config) as connection:
with connection.cursor() as cursor:
cursor.execute("SELECT name FROM country ORDER BY name")
for index, row in enumerate(cursor, start=1):
print(f"{index}. {row[0]}")
Пояснение: используем enumerate(cursor, start=1), чтобы автоматически пронумеровать строки. Запрос упорядочен по имени страны.