Как исправить ошибку 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)').
    • Используйте контекстный менеджер для соединения с БД, чтобы избежать утечек ресурсов.
    • Обрабатывайте исключения при работе с базой данных, чтобы бот не падал при ошибках.
    • Не закрывайте соединение внутри хендлера, если планируете использовать его далее. Лучше закрывать при завершении работы бота.

    Часто задаваемые вопросы

    Часто задаваемые вопросы