🔌 PyMySQL: соединение и курсор
Для работы с MySQL из Python используем библиотеку pymysql. Соединение удобно открывать через контекстный менеджер with: он автоматически закроет ресурсы, даже если произошла ошибка.
import pymysql
config = {
"host": "ich-db.edu.itcareerhub.de",
"user": "ich1",
"password": "password",
"database": "hr",
"charset": "utf8mb4",
}
После pymysql.connect(**config) получаем объект соединения. Через него создаём курсор и выполняем SQL-запросы методом cursor.execute(sql, params).
🔗 Соединение таблиц
Информация о сотрудниках разбросана по трём таблицам:
employees— имя, фамилия, зарплата,department_id,job_id;departments— название отдела,department_id;jobs— название должности,job_id.
Чтобы получить имя, фамилию, должность и зарплату в одной выборке, соединяем таблицы по внешним ключам:
SELECT first_name, last_name, job_title, salary
FROM employees
JOIN departments ON employees.department_id = departments.department_id
JOIN jobs ON employees.job_id = jobs.job_id
WHERE departments.department_name = %s
ORDER BY salary DESC
JOIN по умолчанию — это INNER JOIN: в результат попадают только те строки, для которых найдено совпадение во всех таблицах.
🛡️ Параметризованные запросы
Название отдела, которое вводит пользователь, нельзя вставлять в SQL-строку через f-string. Вместо этого используем плейсхолдер %s и передаём значение отдельно:
cursor.execute("SELECT * FROM employees WHERE department_id = %s", (department_id,))
Если параметр один, кортеж всё равно нужен: не забудьте запятую (value,).
⚠️ Проверка оператора сравнения
Знак сравнения (>, <, =, >=, <=) — это часть языка SQL, его нельзя передать как параметр %s. Безопасный способ: проверить ввод по белому списку и только потом подставить в строку запроса:
valid_operators = {'>', '<', '=', '>=', '<='}
condition = input("Enter condition: ").strip()
if condition not in valid_operators:
print("Invalid condition.")
else:
query = f"SELECT * FROM t WHERE salary {condition} %s"
cursor.execute(query, (value,))
✅ Валидация пользовательского ввода
Перед использованием ввода проверяем два условия:
- Это целое число —
int()может выброситьValueError. - Число находится в допустимом диапазоне — от 1 до количества отделов.
Если проверка не проходит, программа просит ввести номер снова, а не падает.
🧯 Обработка ошибок
При работе с базой могут возникать ошибки подключения, SQL или ввода. Рекомендуется отлавливать конкретные исключения:
try:
selected_index = int(input("Enter department number: "))
except ValueError:
print("Invalid input. Please enter a number.")
try:
with pymysql.connect(**config) as connection:
...
except pymysql.MySQLError as e:
print("Database error:", e)
✨ Современные практики
- Храните параметры подключения в переменных окружения или файле
.env. - Никогда не собирайте SQL через f-string или конкатенацию с пользовательскими данными.
- Выносите повторяющиеся операции в функции: подключение, печать результата, ввод с проверкой.
- Используйте
withдля автоматического закрытия ресурсов.