在select查询中解决SQLite参数限制

问题描述 投票:1回答:1

我有一个GUI应用程序,其中包含人员列表,其中包含人员的数据库ID及其属性。像这样的东西:

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

此列表可以过滤,因此人们的数量和类型会不时地依赖。要获取Peewee Person对象的列表,我首先获取可见ID列表并使用以下查询:

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, ...])

这会在超过1000人的Windows上引发OperationalError: too many SQL variables错误。这在Peewee和SQLite文档中有记录。在线提供的变通方法通常涉及批量插入以及以块的形式分割动作的方法。有没有办法解决这个限制与提到的SELECT ... WHERE ... IN查询?

在列表推导中获取单独的对象太慢了:

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

也许拆分最多1000个项目中的ID列表,在每个块上使用select查询然后以某种方式组合它们?

peewee
1个回答
0
投票

身份证来自何处?当然,最好的答案是避免使用那么多参数。例如,如果您的ID列表可以表示为某种类型的查询,那么您只需编写一个子查询,例如

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

在上面,我们可以从第一个查询中获取所有用户ID,并将它们作为列表集中传递到第二个查询中。但由于第一个查询(“我所有的朋友”)本身就是一个查询,我们可以组成它们。您也可以使用JOIN而不是子查询,但希望您明白这一点。

如果这是不可能的,并且您认真拥有> 1000个ID的列表......这样的列表在GUI应用程序中有用吗?超过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

但严重的是,我认为你实现这一点的方式存在问题,甚至需要过滤掉这么多的ID。

© www.soinside.com 2019 - 2024. All rights reserved.