SQLAlchemy过滤in_运算符

时间:2013-04-23 00:10:20

标签: python sqlite sqlalchemy

我正在尝试对sqlalchemy中的查询执行简单的过滤操作,如下所示:

q = session.query(Genotypes).filter(Genotypes.rsid.in_(inall))

其中

inall是一个字符串列表 基因型被映射到一个表:     class Genotypes(object):         通

Genotypes.mapper = mapper(Genotypes, kg_table, properties={'rsid': getattr(kg_table.c, 'rs#')})

这对我来说似乎很简单,但是当我通过q.first()执行上述查询时出现以下错误:

  

" sqlalchemy.exc.OperationalError :( OperationalError)SQL太多了   变量u' SELECT"然后是 inall 中的1M项目列表   名单。但它们不应该是SQL变量,只是一个列表   成员资格是过滤标准。

我是否错误地进行了过滤?

(db是sqlite)

2 个答案:

答案 0 :(得分:17)

如果您从rsid获取Genotypes的表格在同一个数据库中可用,我会使用subquery将它们传递到您的sq = session.query(RSID_Source).subquery() q = session.query(Genotypes).filter(Genotypes.rsid.in_(sq)) 查询中,而不是通过你的Python代码中有数百万个条目。

in

问题是,为了将该列表传递给SQLite(或任何数据库,实际上),SQLAlchemy必须将-- Not valid SQLite SQL DECLARE @Param1 TEXT; SET @Param1 = ?; DECLARE @Param2 TEXT; SET @Param2 = ?; -- snip 999,998 more SELECT field1, field2, -- etc. FROM Genotypes G WHERE G.rsid IN (@Param1, @Param2, /* snip */) 子句的每个条目作为变量传递。 SQL大致翻译为:

{{1}}

答案 1 :(得分:4)

以下解决方法对我有用:

q = session.query(Genotypes).filter(Genotypes.rsid.in_(inall))
query_as_string = str(q.statement.compile(compile_kwargs={"literal_binds": True}))
session.execute(query_as_string).first()

这基本上会强制查询在执行前编译为字符串,从而绕过整个变量问题。有关此内容的一些详细信息,请参见SQLAlchemy的文档here

顺便说一句,如果您不使用SQLite,可以使用ANY运算符将列表对象作为单个参数传递(请参阅我对此问题的回答here)。