Как исправить ошибку sqlite3.OperationalError: no such column в Python
При разработке Telegram-бота на Python с использованием библиотеки aiogram и базы данных SQLite вы можете столкнуться с ошибкой sqlite3.OperationalError: no such column: ilya. Эта проблема возникает из-за неправильного форматирования SQL-запроса при вставке строковых значений. В этой статье мы разберём причины ошибки и покажем правильные способы работы с SQLite.
Почему возникает ошибка no such column?
Ошибка появляется, когда вы подставляете значение переменной напрямую в SQL-запрос без кавычек. Например, в коде cur.execute(f'INSERT INTO result(name) VALUES ({data["Name"]})') Python подставляет значение ilya без кавычек, и SQLite интерпретирует его как имя столбца. Если столбца с таким именем не существует, выбрасывается исключение OperationalError.
Как правильно вставлять данные в SQLite из Python?
1. Использование параметризованных запросов (рекомендуемый способ)
Самый безопасный и надёжный метод - передавать значения через параметры запроса. Это защищает от SQL-инъекций и автоматически экранирует строки.
cur.execute('INSERT INTO result(name) VALUES (?)', (data['Name'],))2. Использование f-строк с ручным экранированием (не рекомендуется)
Если вы всё же хотите использовать f-строки, обязательно оборачивайте строковые значения в одинарные кавычки:
cur.execute(f"INSERT INTO result(name) VALUES ('{data["Name"]}')")Но такой подход уязвим для SQL-инъекций и может привести к ошибкам, если имя содержит кавычки.
Исправленный код для Telegram-бота
В вашем коде есть две проблемы: вставка имени и класса без кавычек. Вот корректный вариант функции reg3:
@router.message(Reg.School_class)
async def reg3(message: Message, state: FSMContext):
await state.update_data(School_class=message.text)
data = await state.get_data()
# Правильная вставка через параметры
cur.execute('INSERT INTO result(name) VALUES (?)', (data['Name'],))
db.commit()
cur.execute('INSERT INTO result(school_class) VALUES (?)', (data['School_class'],))
db.commit()
await message.answer(f'Хорошо! Мы закончили. Ваше имя: {data["Name"]}, Класс: {data["School_class"]}')
await state.clear()Обратите внимание: во втором запросе мы используем столбец school_class, а не name, так как вы сохраняете класс в отдельном поле. Убедитесь, что в таблице result есть оба столбца.
Дополнительные рекомендации по работе с SQLite в aiogram
- Создавайте таблицу с нужными столбцами перед вставкой данных. Например:
cur.execute('CREATE TABLE IF NOT EXISTS result (id INTEGER PRIMARY KEY, name TEXT, school_class TEXT)'). - Используйте контекстный менеджер для соединения с БД, чтобы избежать утечек ресурсов.
- Обрабатывайте исключения при работе с базой данных, чтобы бот не падал при ошибках.
- Не закрывайте соединение внутри хендлера, если планируете использовать его далее. Лучше закрывать при завершении работы бота.