2013-04-23 167 views
11

我試圖做的SQLAlchemy的查詢一個簡單的過濾器操作,像這樣:SQLAlchemy的過濾器IN_操作

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

其中

inall是一個字符串列表 基因型被映射到表: 類基因型(對象): 通

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

這看起來非常簡單給我,但我得到的F當我執行上述查詢時出現錯誤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的)

回答

14

如果你在哪裏得到您的rsid S中的表可在同一數據庫中,我會使用一個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 */) 
1

以下解決方法爲我工作:

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)。