Jan*_*Jan 6 python postgresql sqlalchemy
我尝试SELECT ... WHERE id IN (1,2,3)有效地使用 Sqlalchemy 和 Postges。
如果我做一个简单的选择:
s.query(Model).filter(Model.id.in_([1,2,3])).all()
Run Code Online (Sandbox Code Playgroud)
Sqlalchemy 运行这个查询:
SELECT model.id AS model_id FROM model
WHERE model.id IN (%(id_1)s, %(id_2)s, %(id_3)s)
{'id_1': 1, 'id_2': 2, 'id_3': 3}
Run Code Online (Sandbox Code Playgroud)
当数组变长时,这不是有效的。这也不适用于烘焙查询。
知道 Postgres 支持元组作为参数,我尝试使用绑定参数将我的数组/元组直接放入参数部分:
s.query(Model)
.filter(Model.id.in_(bindparam('my_tuple')))
.params(my_tuple=(1,2,3)).all()
Run Code Online (Sandbox Code Playgroud)
不幸的是SQLAlchemy的不接受bindparam在in_:
sqlalchemy.exc.InvalidRequestError:
in_() accepts either a list of expressions or a selectable:
BindParameter('my_tuple', None, type_=NullType())
Run Code Online (Sandbox Code Playgroud)
所以我试图以某种方式欺骗 Sqlalchemy 接受bindparam.
扩展BindParam课程我能够这样做:
class TupleBindParameter(BindParameter, Selectable):
pass
s.query(Model)
.filter(Model.id.in_(TupleBindParameter('my_tuple')))
.params(my_tuple=(1,2,3)).all()
Run Code Online (Sandbox Code Playgroud)
现在我得到了我想要的:
SELECT model.id AS model_id FROM model
WHERE model.id IN %(my_tuple)s
{'my_tuple': (1, 2, 3)}
Run Code Online (Sandbox Code Playgroud)
这个解决方案对我来说似乎有点hacky。有没有官方的方法让 Sqlalchemy 做同样的事情?
——
重现我的示例的设置非常简单:
Base = declarative_base()
class Model(Base):
__tablename__ = 'model'
id = Column(Integer, primary_key=True)
def __init__(self, id): self.id = id
engine = create_engine('postgres://x:x@localhost/x')
Base.metadata.create_all(bind=engine)
Session = sessionmaker(bind=engine)
s = Session()
s.add_all([Model(1), Model(2), Model(4)])
s.commit()
Run Code Online (Sandbox Code Playgroud)
用 op('IN')
s.query(Model)
.filter(Model.id.op('IN')(bindparam('my_tuple')))
.params(my_tuple=(1,2,3)).all()
Run Code Online (Sandbox Code Playgroud)
看到这个问题
| 归档时间: |
|
| 查看次数: |
728 次 |
| 最近记录: |