Sqlalchemy 复杂的 in_ 子句与元组列表
我正在寻找一种方法,让SQLAlchemy生成如下形式的查询:
select * from t where (a,b) in ((a1,b1),(a2,b2));
这可能吗?
如果不行,有什么建议可以模拟这个查询吗?
4 个回答
31
使用 tuple_
:
from sqlalchemy import tuple_
keys = [(a1, b1), (a2, b2)]
session.query(T).filter(tuple_(T.a, T.b).in_(keys)).all()
http://docs.sqlalchemy.org/en/latest/core/sqlelement.html#sqlalchemy.sql.expression.tuple_
3
首先,感谢上面的Hao Lian,我想出了一个可行但有点麻烦的解决方案。
假设我们有一个声明式风格的映射类,叫做Clazz
,还有一个包含复合主键值的元组列表,叫做values
。(我编辑了一下,使用了我认为更好的SQL生成风格):
from sqlalchemy.sql.expression import text,bindparam ... def __gParams(self, f, vs, ts, bs): for j,v in enumerate(vs): key = f % (j+97) bs.append(bindparam(key, value=v, type_=ts[j])) yield ':%s' % key def __gRows(self, ts, values, bs): for i,vs in enumerate(values): f = '%%c%d' % i yield '(%s)' % ', '.join(self.__gParams(f, vs, ts, bs)) def __gKeys(self, k, ts): for c in k: ts.append(c.type) yield str(c) def __makeSql(self,Clazz, values): t = [] b = [] return text( '(%s) in (%s)' % ( ', '.join(self.__gKeys(Clazz.__table__.primary_key,t)), ', '.join(self.__gRows(t,values,b))), bindparams=b)
这个解决方案适用于复合主键或简单主键。不过,对于简单主键来说,它的速度可能比col.in_(keys)
稍慢一点。
我仍然希望能听到更好的解决方案,但目前这个方法是有效的,并且比or_(and_(conditions))
的方法,或者for key in keys: do_stuff(q.get(key))
的方法表现得更好。