2013-04-23 6 views
11

मैं, SQLAlchemy में एक प्रश्न पर एक साधारण फिल्टर आपरेशन करने के लिए कोशिश कर रहा हूँ इस तरह:SQLAlchemy फिल्टर in_ ऑपरेटर

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

जहां

ऑडियो एवं वीडियो कंप्यूटर स्ट्रिंग की एक सूची है जीनोटाइप एक मेज पर मैप किया गया है : वर्ग जीनोटाइप (वस्तु): पास

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

यह सुंदर मेरे लिए सरल लगता है, लेकिन मैं च मिल त्रुटि ollowing जब मैं 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.

Am मैं गलत तरीके से छानने कर?

उत्तर

14

तो तालिका तुम कहाँ से अपने rsid रों हो रही है उपलब्ध है एक ही डेटाबेस में मैं एक subquery का उपयोग करेंगे एक लाख से गुजर के बजाय अपना Genotypes क्वेरी में उन्हें पारित करने के लिए (db SQLite है) आपके पायथन कोड में चारों ओर प्रविष्टियां।

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

नीचे वैकल्पिक हल मेरे लिए काम किया:

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 का उपयोग नहीं कर रहे हैं तो आप सूची ऑब्जेक्ट को एक पैरामीटर के रूप में पास करने के लिए किसी भी ऑपरेटर का उपयोग कर सकते हैं (इस प्रश्न का मेरा उत्तर देखें here)।