Sqlalchemy complex in_子句与元组列表中的元组

los*_*gic 6 python sql sqlalchemy

我正在尝试找到一种方法使SQLAlchemy生成以下形式的查询:

select * from t where (a,b) in ((a1,b1),(a2,b2));

这可能吗?

如果没有,任何关于模仿它的方法的建议?

Ano*_*oop 22

用途tuple_:

keys = [(a1, b1), (a2, b2)]
session.query(T).filter(tuple_(T.a, T.b).in_(keys)).all()
Run Code Online (Sandbox Code Playgroud)

http://docs.sqlalchemy.org/en/latest/core/sqlelement.html#sqlalchemy.sql.expression.tuple_

  • 警告 警告(来自 sqlalchemy 文档):并非所有后端都支持复合 IN 构造,目前已知可在 PostgreSQL 和 MySQL 上运行,但不适用于 SQLite。当调用此类表达式时,不受支持的后端将引发 DBAPIError 的子类。 (2认同)

los*_*gic 3

好吧,感谢上面的郝连,我想出了一个实用但痛苦的解决方案。

假设我们有一个声明式映射类,Clazz以及一个list复合主键值的元组,values (编辑为使用更好的(IMO)sql 生成样式):

从 sqlalchemy.sql.expression 导入文本,bindparam
...
    def __gParams(self, f, vs, ts, bs):
        对于枚举(vs)中的 j,v:
            键 = f % (j+97)
            bs.append(bindparam(key, value=v, type_=ts[j]))
            产量 ':%s' % 键

    def __gRows(self, ts, 值, bs):
        对于枚举(值)中的 i,vs:
            f = '%%c%d' % i
            产量 '(%s)' % ', '.join(self.__gParams(f, vs, ts, bs))

    def __gKeys(self, k, ts):
        对于 k 中的 c:  
            ts.append(c.type)
            产量 str(c)

    def __makeSql(self,Clazz, 值):
        t = []
        b = []
        返回文本(
                '(%s) 在 (%s)' % (
                    ', '.join(self.__gKeys(Clazz.__table__.primary_key,t)),
                    ', '.join(self.__gRows(t,values,b))),
                绑定参数=b)

该解决方案适用于复合或简单主键。不过,它可能比col.in_(keys)简单主键稍微慢一些。

我仍然对更好的方法的建议感兴趣,但这种方法目前有效,并且性能明显优于以前的or_(and_(conditions))方法for key in keys: do_stuff(q.get(key))