SQLAlchemy过滤器

2024-06-16 11:05:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图对sqlalchemy中的查询执行一个简单的筛选操作,如下所示:

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

其中

inall是字符串列表 基因型映射到一个表: 类别基因型(对象): 通过

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" followed by a list of the 1M items in the inall list. But they aren't supposed to be SQL variables, just a list whose membership is the filtering criteria.

我的过滤有误吗?

(数据库是sqlite)


Tags: theinsqlsqlalchemysessiontablevariableslist
2条回答

下面的解决方法对我有效:

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运算符将list对象作为单个参数传递(请参阅我对这个问题的回答here)。

如果从中获取rsids的表在同一个数据库中可用,我将使用subquery将它们传递到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 */)

相关问题 更多 >