19

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

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

在哪里

inall 是一个字符串列表 Genotypes 映射到一个表:class Genotypes(object): pass

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

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

"sqlalchemy.exc.OperationalError: (OperationalError) too many SQL variables u'SELECT" 后跟 inall 列表中 1M 项的列表 。但它们不应该是 SQL 变量,而只是一个列表,其成员资格是过滤条件。

我做的过滤不正确吗?

(数据库是 sqlite)

4

2 回答 2

22

如果您rsid从中获取 s 的表在同一个数据库中可用,我会使用子查询将它们传递到您的Genotypes查询中,而不是在 Python 代码中传递一百万个条目。

sq = session.query(RSID_Source).subquery()
q = session.query(Genotypes).filter(Genotypes.rsid.in_(sq))

问题是,为了将该列表传递给 SQLite(或任何数据库,真的),SQLAlchemy 必须将您的in子句的每个条目作为变量传递。SQL 大致翻译为:

-- 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 */)
于 2013-04-23T00:30:29.307 回答
6

以下解决方法对我有用:

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 文档。

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

于 2017-03-07T07:09:53.783 回答