Python 使用session.query通过SQLAlchemy ORM更新联接表
使用MySQL,我想生成以下SQL:Python 使用session.query通过SQLAlchemy ORM更新联接表,python,mysql,sqlalchemy,Python,Mysql,Sqlalchemy,使用MySQL,我想生成以下SQL: UPDATE tableA INNER JOIN tableB ON tableA.some_id = tableB.some_id SET tableA.foo = 1 WHERE tableB.bar IN ('baz','baaz') 这是我的SQLAlchemy查询: session.query(tableA).join(tableB, tableA.some_id == tableB.some_id) \
UPDATE tableA
INNER JOIN tableB
ON tableA.some_id = tableB.some_id
SET tableA.foo = 1
WHERE tableB.bar IN ('baz','baaz')
这是我的SQLAlchemy查询:
session.query(tableA).join(tableB, tableA.some_id == tableB.some_id) \
.filter(tableB.bar.in_(['baz','baaz']))\
.update({tableA.foo: 1})
但它生成的SQL是这样的(一个多表更新,没有连接条件,这不是我想要的):
我尝试将.join更改为另一个.filter以指定连接条件,但没有解决问题。
如何强制这个简单的update语句进行正确的连接?我想我也遇到了同样的问题。以下是我的解决方案:
query = update(Model).values(field=123)
query = query.where(Model.parent_model_id == ParentModel.id)
query = query.where(ParentModel.grand_parent_id == GrandParentModel.id)
query = query.where(GrandParentModel.name == 'foobar')
session.execute(query)
从版本0.7.4开始,允许您在WHERE子句中引用多个表。这样,您就可以构建并执行如下表达式:
users.update().values(name='ed').where(
users.c.name==select([addresses.c.email_address]).\
where(addresses.c.user_id==users.c.id).\
as_scalar()
)
(示例直接来自上面的链接)
ValAyal遇到的问题实际上是因为Query.join()
不支持Query.update()
。不幸的是,在0.9.1之前,它一直在默默地生成类似上面ValAyal共享的查询。注意,该行为已修改为发出警告:
[orm][bug]查询不支持联接、子选择或特殊来源
使用Query.update()或Query.delete()方法时的子句;
如果像Query.join()这样的方法
或Query.select_from()已被调用,将发出警告。截至
1.0.0b5这将引发错误
参考资料:
实际上,我们在我今晚工作的地方遇到了这个问题,发现我们的代码实际上发出了以下警告(这表示它将在1.0中出错):
在我们的例子中,我们选择将更新转换为select和update to one表。您解决了这个问题吗?我有一些几乎相同的东西,我正在努力寻找解决办法(两个查询而不是一个查询)。向上投票如果你正在为同样的问题苦苦挣扎,也许有人会看到。请注意,这里的示例不是多表更新,而是使用子查询引用多个表的标准SQL方法。这对sqlite不起作用,但可能对其他DB后端起作用
users.update().values(name='ed').where(
users.c.name==select([addresses.c.email_address]).\
where(addresses.c.user_id==users.c.id).\
as_scalar()
)
SAWarning: Can't call Query.update() or Query.delete() when join(), outerjoin(), select_from(), or from_self() has been called. This will be an exception in 1.0
self._validate_query_state()