Как получить данные из базы данных SQLite в боте, созданном с использованием aiogram?

Я новичок в Python и разрабатываю бота для Telegram. Мне нужно извлекать определенные строки из базы данных, если будут найдены соответствия. Как правильно это реализовать? Я не смог найти нужную информацию в интернете. Вот что я уже попробовал сделать: <br/> <br/> <pre><code class="python">@start_router.message(Form.searсh_for_name)
async def search_name(message: types.Message):
    message_name = message.text.strip()
    async with aiosqlite.connect('base.db') as db:
        await db.execute('SELECT username, user_tg, name, soname FROM user WHERE [name] = "message_name"')
        users = db.fetchall()
        users_str = "\n".join([str(user) for user in users])
        await message.answer(users_str)
        await db.commit()</code></pre> <br/> <br/> Но у меня возникает ошибка: AttributeError: 'Connection' object has no attribute 'fetchall'. Я понимаю причину ошибки, но мне кажется, что основной подход неверен. Не могли бы вы помочь?
  • 8 января 2025 г. 13:34
Ответы на вопрос 3
Конечно! Я помогу вам исправить ваш код для извлечения данных из базы данных SQLite с использованием `aiogram`. 

Сначала давайте взглянем на основные моменты в вашем коде. Ошибка `AttributeError: 'Connection' object has no attribute 'fetchall'` происходит, потому что вы пытаетесь вызвать метод `fetchall` на объекте соединения, в то время как необходимым действием для получения данных является использование курсора.

Вот правильный подход:

1. Создайте курсор для выполнения SQL-запроса.
2. Воспользуйтесь методом `fetchall()` на курсоре, а не на соединении.

Также ваш SQL-запрос содержит ошибку в подстановке параметров. Вы должны использовать параметризированные запросы, чтобы избежать SQL-инъекций.

Вот исправленный пример вашего кода:

```python
from aiogram import types
from aiogram.dispatcher import F
from aiosqlite import connect

@start_router.message(Form.searсh_for_name)
async def search_name(message: types.Message):
    message_name = message.text.strip()
    async with connect('base.db') as db:
        async with db.execute('SELECT username, user_tg, name, soname FROM user WHERE name = ?', (message_name,)) as cursor:
            users = await cursor.fetchall()
            if users:  # Проверяем, если есть результаты
                users_str = "\n".join([f"Username: {user[0]}, TG: {user[1]}, Name: {user[2]}, Surname: {user[3]}" for user in users])
            else:
                users_str = "Пользователи не найдены."
        
            await message.answer(users_str)
```

### Разбор изменений:

1. **Параметризированный запрос**: Теперь в SQL-запросе используется `?` для подстановки значения `message_name`. Это защищает от SQL-инъекций.
   
2. **Использование курсора**: Мы использовали `async with db.execute(...) as cursor`, чтобы создать курсор для выполнения запроса. Затем вызвали `await cursor.fetchall()` для получения всех строк результата.

3. **Проверка результатов**: Проверяем, получили ли мы пользователей из базы данных. Если нет, отправляем сообщение об этом.

4. **Форматирование вывода**: Для лучшего представления информации, мы отформатировали вывод, чтобы сделать его более читабельным.

Обязательно проверьте, чтобы библиотека `aiosqlite` была установлена. Если она еще не установлена, вы можете сделать это с помощью `pip`:

```bash
pip install aiosqlite
```

Теперь ваш бот должен корректно извлекать данные из базы данных SQLite!
Сначала создай курсор , потом на нём уже вызывай execute() для выполнения запросов. Когда закончишь работать с курсором - вызови close() . Это часть спецификации DB-API 2.0, которому следует большинство библиотек для работы с БД на питоне.
Если у тебя эта же ошибка возникает и без телеграма, то упоминание телеграма можно полностью убрать из вопроса. 
Проблема у тебя только с тем, что ты не читал документацию от aiosqlite и пытаешься с ним работать как с синхронным sqlite.

https://aiosqlite.omnilib.dev/en/stable/api.html#c...

У Connection действительно нет метода fetchall.
Нужно использовать метод execute_fetchall.
Либо используй курсоры, что предпочтительней.

PS: у многих новичков возникают трудности, когда они сразу пытаются делать большой проект, где сочетаются разные фреймворки/библиотеки/технологии. Пока ты не освоился с языком и не научился ориентироваться в документации - лучше попробуй с чего-то более простого.

Например, если хочешь поработать с телегой - сделай сначала хранение данных полностью в оперативной памяти на списках и словарях.

Если хочешь поработать с sqlite - попробуй в качестве интерфейса пользователя использовать консоль
Похожие вопросы