Почему SELECT photo возвращает пустой список, хотя данные есть
При работе с SQLite через Python разработчики часто сталкиваются с ситуацией, когда запрос на получение фото из базы данных возвращает пустой список, хотя записи в таблице присутствуют. Рассмотрим типичный пример на aiosqlite и sqlite3 и разберём способы устранения ошибки.
Типичный код с ошибкой
В исходном коде используется асинхронная функция select_game_photo_for_id, которая выполняет запрос SELECT photo FROM games WHERE game_name = ? AND tg_id = ?. Если результат fetchall() пуст, проблема может быть в передаче параметров или в структуре самой базы данных.
Основные причины пустого результата
1. Несовпадение типов данных
Параметр title может передаваться как строка, а в базе данных game_name хранится с лишними пробелами, в другом регистре или в кодировке, отличной от UTF-8. Проверьте точное содержимое поля game_name в таблице.
2. Проблемы с идентификатором tg_id
Параметр tg_id может быть передан как int, но в базе данных поле имеет тип TEXT или наоборот. Убедитесь, что типы совпадают. Например, если в таблице tg_id хранится как строка, передавайте его как строку: str(tg_id).
3. Отсутствие коммита после вставки
Если вы вставляете фото в базу данных в другой функции, но не вызываете con.commit() после INSERT, то данные фактически не сохраняются. В приведённом коде commit() стоит после SELECT, что не имеет смысла - SELECT не изменяет данные.
4. Использование неправильного соединения
Если приложение работает в многопоточной или асинхронной среде, возможно, соединение с базой данных было закрыто или перезаписано. Рекомендуется использовать одно соединение на протяжении всего сеанса или проверять его состояние.
Как исправить код
Вот исправленная версия функции с добавлением отладки и проверки типов:
import sqlite3
def select_game_photo_for_id(title: str = None, tg_id: int = None):
with sqlite3.connect('game_launch.db') as con:
cur = con.cursor()
# Приводим title к нижнему регистру и убираем пробелы
title_clean = title.strip().lower() if title else ''
# Выполняем запрос с явным приведением типов
cur.execute('''SELECT photo FROM games WHERE LOWER(game_name) = ? AND tg_id = ?''', (title_clean, tg_id))
result = cur.fetchall()
# Для отладки выводим количество найденных записей
print(f'Найдено записей: {len(result)}')
return resultДополнительные рекомендации
- Используйте
fetchone(), если ожидаете только одну запись - это ускорит работу. - Добавьте индексы на поля
game_nameиtg_idдля ускорения поиска. - Логируйте SQL-запросы - выводите в консоль сам запрос с подставленными параметрами, чтобы увидеть реальные значения.
- Проверьте права доступа к файлу базы данных - возможно, он открыт в режиме только для чтения.
Заключение
Пустой список при SELECT photo из SQLite в Python чаще всего вызван несоответствием типов данных или отсутствием коммита после вставки. Проверьте параметры запроса, используйте отладку и убедитесь, что данные действительно сохранены. После внесения исправлений функция будет возвращать корректные фото из базы данных.