Обойти ограничение параметра SQLite в запросе выбора - PullRequest
0 голосов
/ 12 февраля 2019

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

+----+------+
| ID | Name |
+----+------+
|  1 | John |
|  2 | Fred |
|  3 | Mary |
[...]

Этот список можно отфильтровать, поэтому количество и тип людей время от времени зависят.Чтобы получить список объектов Peewee Person, я сначала получаю список видимых идентификаторов и использую следующий запрос:

ids = [row[0] for row in store]
Person.select().where(Person.id.in_(ids))

, что, в свою очередь, приводит к следующему SQL:

('SELECT "t1"."id", "t1"."name" FROM "person" AS "t1" WHERE ("t1"."id" IN (?, ?, ?, ...))', [1, 2, 3, ...])

Это приводит к ошибке OperationalError: too many SQL variables в Windows с более чем 1000 человек.Это задокументировано в документах Peewee и SQLite.Обходные пути, предоставляемые онлайн, обычно относятся к групповым вставкам и способам разделения действия на куски.Есть ли способ обойти это ограничение с помощью упомянутого запроса SELECT ... WHERE ... IN?

Слишком медленное получение отдельных объектов в списке:

people = [Person.get_by_id(row[0]) for row in store]

Возможно разделить список идентификаторовв макс. 1000 элементов используйте запрос выбора для каждого чанка, а затем объедините их как-нибудь?

1 Ответ

0 голосов
/ 13 февраля 2019

Откуда поступают идентификаторы?Конечно, лучший ответ - избегать использования такого количества параметров.Например, если ваш список идентификаторов может быть представлен как какой-то запрос, то вы можете просто написать подзапрос, например,

my_friends = (Relationship
              .select(Relationship.to_user)
              .where(Relationship.from_user == me))
tweets_by_friends = Tweet.select().where(Tweet.user.in_(my_friends))

. Выше мы могли бы получить все идентификаторы пользователей из первогозапрос и передать их в виде списка во второй запрос.Но поскольку первый запрос («все мои друзья») сам по себе является запросом, мы можем просто составить его.Вы также можете использовать JOIN вместо подзапроса, но, надеюсь, вы получите точку.

Если это невозможно, и у вас серьезно есть список из> 1000 идентификаторов ... как такой список полезен вПриложение с графическим интерфейсом?Более 1000 вещей - это довольно много вещей.

Чтобы попытаться ответить на вопрос, который вы задали, вам придется разбить их на части.Что хорошо.Просто:

user_ids = list_of_user_ids
accum = []
# 100 at a time.
for i in range(0, user_ids, 100):
    query = User.select().where(User.id.in_(user_ids[i:i+100]))
    accum.extend([user for user in query])
return accum

А если серьезно, я думаю, что есть проблема с тем, как вы реализуете это, что делает даже необходимой фильтрацию на очень многих идентификаторах.

...