我正在尝试对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)
答案 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)。