В этом уроке мы изучим одну из самых важных тем при работе с базами данных в Python — **параметризованные запросы**. Это ключевой механизм защиты от SQL-инъекций. Вы научитесь правильно передавать данные в SQL-запросы, используя плейсхолдеры (заполнители) вместо форматирования строк. Мы разберем разницу между безопасными и небезопасными методами, научимся формировать кортежи параметров и применять их в методе execute(). Задания построены от простых концепций к написанию рабочего кода.
- Модуль 1: Основы синтаксиса Python
- Модуль 2: Переменные и типы данных
- Модуль 3: Операторы
- Арифметические операторы (+, -, *, /).
- Целочисленное деление и остаток (// и %).
- Возведение в степень (**).
- Операторы сравнения.
- Логические операторы (and, or, not).
- Операторы присваивания (=, +=, -=).
- Операторы принадлежности (in, not in).
- Операторы идентичности (is, is not).
- Битовые операторы.
- Тернарный оператор.
- Модуль 4: Ввод и вывод данных
- Модуль 5: Условные конструкции
- Модуль 6: Циклы
- Модуль 7: Строки
- Модуль 8: Списки
- Модуль 9: Кортежи
- Модуль 10: Словари
- Модуль 11: Множества
- Модуль 12: Функции
- Модуль 13: Встроенные функции
- Модуль 14: Работа с файлами
- Модуль 15: Обработка исключений
- Модуль 16: Модули и пакеты
- Модуль 17: ООП - Основы
- Модуль 18: ООП - Продвинутый уровень
- Модуль 19: Декораторы
- Модуль 20: Генераторы и итераторы
- Модуль 21: Регулярные выражения
- Модуль 22: Дата и время
- Модуль 23: Математические операции
- Модуль 24: Работа с сетью
- Модуль 25: Асинхронное программирование
- Модуль 26: Многопоточность
- Модуль 27: Тестирование
- Модуль 28: Базы данных
- CRUD операции.
- Параметризованные запросы.
- Модуль 29: Алгоритмы и структуры данных
- Модуль 30: Продвинутые возможности
Безопасно или Уязвимо?
Распределите примеры вызовов SQL-запросов по двум категориям: "Безопасно (Параметризация)" и "Уязвимо (SQL-инъекция)". Помните, что использование f-строк или конкатенации для подстановки значений в SQL — это плохая практика.
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")cursor.execute("INSERT INTO log VALUES (?)", (data,))query = "SELECT * FROM items WHERE name = '" + name + "'"cursor.execute(query)cursor.execute("UPDATE stats SET count = ? WHERE label = ?", (10, 'hits'))Элементы параметризованного запроса
Сопоставьте элементы кода (слева) с их ролью в параметризованном запросе (справа).
Ошибка в передаче параметров
В данном коде есть распространенная ошибка при передаче одного параметра. Метод `execute` ожидает последовательность (кортеж или список) вторым аргументом, даже если параметр всего один. Найдите и исправьте строку с ошибкой.
product_id = 42# Ошибка: пропущена запятая для создания кортежаcursor.execute("SELECT price FROM goods WHERE id=?", (product_id))result = cursor.fetchone()Безопасная вставка данных
Допишите код для добавления нового пользователя. Используйте параметризацию, чтобы избежать ошибок и уязвимостей. Данные для вставки находятся в переменных `name` и `age`.
name = "Alice"
age = 30
# Вставляем 2 значения, нужны 2 плейсхолдера
cursor.execute("INSERT INTO users (name, age) VALUES (input1S, input2S)", input3S)
conn.commit()Поиск с фильтрацией
Соберите код, который ищет книги, цена которых меньше заданной переменной `max_price`. Используйте безопасный синтаксис `sqlite3`.
max_price = 500
sql = "SELECT title FROM books WHERE input1S"
cursor.execute(input2S, input3S)Последовательность обновления данных
Расставьте строки кода в правильном порядке, чтобы обновить email пользователя. Обратите внимание на порядок: подготовка данных -> выполнение запроса -> фиксация изменений.
new_email = 'new@example.com'user_id = 101cursor.execute("UPDATE users SET email = ? WHERE id = ?", (new_email, user_id))conn.commit()Безопасная регистрация пользователя
Соберите функцию `register_user`, которая принимает логин и пароль и безопасно вставляет их в базу данных. Остерегайтесь небезопасного варианта с f-строкой (decoy).
def register_user(login, password): query = "INSERT INTO users (login, pass) VALUES (?, ?)" cursor.execute(query, (login, password)) conn.commit() query = f"INSERT INTO users VALUES ('{login}', '{password}')" cursor.execute(query)Что произойдет при выполнении?
Проанализируйте код. В таблице `products` есть товар 'Apple' с ценой 100. Мы пытаемся обновить цену. Какой будет результат выполнения этого кода?
new_price = 120
# Ошибка: передано просто число, а не кортеж (120,)
try:
cursor.execute("UPDATE products SET price=? WHERE name='Apple'", (new_price))
print("Success")
except TypeError:
print("Error: Parameters must be a sequence")
except Exception as e:
print("Other Error")