2013-04-23 25 views
11

私はこのように、SQLAlchemyの中のクエリ上の単純なフィルタ演算を行うにしようとしています:SQLAlchemyのフィルタIN_演算子

inallが文字列 遺伝子型のリストがテーブルにマップされている

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

: クラスの遺伝子型(オブジェクト): パス

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

これは私には非常に簡単そうですが、私はFを取得します私はq.first()を行うことによって、上記のクエリを実行したときにエラーをollowing:

"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.

私が間違ってフィルタリングをやっていますか?

私はsubqueryを使用していたものと同じデータベースに

答えて

14

あなたからあなたのrsid秒を取得しているテーブルが利用可能である場合に百万を渡すのではなく、あなたのGenotypesクエリにそれらを渡すために(デシベルはsqliteのです)あなたのPythonコード内のエントリ。

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

問題はSQLiteのにそのリスト(または任意のデータベース、本当に)を渡すために、SQLAlchemyのは、変数としてごin句の各エントリの上に通過しなければならないということです。以下の回避策は、私のために働いた

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

:SQLは、にほぼ翻訳

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の答えを参照)。

関連する問題