使用 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) \
.filter(tableB.bar.in_(['baz','baaz']))\
.update({tableA.foo: 1})
但是它生成的SQL是这样的(多表更新,没有join条件,这不是我想要的):
UPDATE tableA, tableB
SET tableA.foo = 1
WHERE tableB.bar IN ('baz','baaz')
我已经尝试将 .join 更改为另一个 .filter 以指定连接条件,但这并没有解决问题。 我如何强制这个简单的更新语句进行正确的连接?
最佳答案
自版本 0.7.4 起sqlalchemy.sql.expression.update确实允许您在 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 一样。 changelog notes for 0.9.1注意到该行为已修改为发出警告:
[orm] [bug] Query doesn’t support joins, subselects, or special FROM clauses when using the Query.update() or Query.delete() methods; instead of silently ignoring these fields if methods like Query.join() or Query.select_from() has been called, a warning is emitted. As of 1.0.0b5 this will raise an error.
References: #3349
我们今天晚上在我工作的地方遇到了这个问题,发现我们的代码实际上发出了以下警告(表示它将在 1.0 中出错):
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()
在我们的例子中,我们选择将更新转换为选择和对一个表的更新。
关于python - 使用 session.query 通过 SQLAlchemy ORM 更新连接表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33153823/