使用 session.query 通过 SQLAlchemy ORM 更新连接表 [英] Update joined table via SQLAlchemy ORM using session.query

查看:66
本文介绍了使用 session.query 通过 SQLAlchemy ORM 更新连接表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 MySQL,我想生成此 SQL:

Working with MySQL, I'd like to generate this SQL:

UPDATE tableA
INNER JOIN tableB
ON tableA.some_id = tableB.some_id
SET tableA.foo = 1
WHERE tableB.bar IN ('baz','baaz')

这是我的 SQLAlchemy 查询:

This is my SQLAlchemy query:

session.query(tableA).join(tableB, tableA.some_id == tableB.some_id) \
                     .filter(tableB.bar.in_(['baz','baaz']))\
                     .update({tableA.foo: 1})

但是它生成的SQL是这样的(多表更新,没有连接条件,这不是我想要的):

But the SQL it generates is this (a multi-table update, with no join condition, which is not what I want):

UPDATE tableA, tableB 
SET tableA.foo = 1
WHERE tableB.bar IN ('baz','baaz')

我尝试将 .join 更改为另一个 .filter 以指定连接条件,但这并没有解决问题.如何强制这个简单的更新语句进行正确的连接?

I've tried changing the .join into another .filter to specify the join condition, that didn't solve the problem. How do I force this simple update statement to do the proper join?

推荐答案

从 0.7.4 版本开始 sqlalchemy.sql.expression.update 确实允许您在 WHERE 子句中引用多个表.有了这个,你可以构建和执行一个表达式:

As of version 0.7.4 sqlalchemy.sql.expression.update does allow you to refer to multiple tables in the WHERE clause. With this, you could build and execute an expression like:

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.update() 不支持 Query.join().不幸的是,在 0.9.1 之前,它会默默地生成类似于上面共享的 ValAyal 的查询.0.9.1 的变更日志说明 指出该行为被修改为发出警告:

The problem ValAyal is having is actually because Query.join() is not supported with Query.update(). Unfortunately, until 0.9.1 this was silently generating queries like the one ValAyal shared above. The changelog notes for 0.9.1 notes that the behavior was modified to emit a warning:

[orm] [bug] 查询不支持连接、子选择或特殊的 FROM使用 Query.update() 或 Query.delete() 方法时的子句;如果像 Query.join() 这样的方法,而不是默默地忽略这些字段或 Query.select_from() 已被调用,发出警告.作为1.0.0b5 这将引发错误.

[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.

参考:#3349

我们实际上在今晚工作的地方遇到了这个问题,发现我们的代码实际上发出了以下警告(表示它将在 1.0 中出错):

We actually ran into this where I work just this evening and found that our code is, in fact, emitting the following warning (which says it will an error in 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()

在我们的例子中,我们选择将更新转换为一个选择和一个表的更新.

In our case, we opted to convert the update into a select and an update to one table.

这篇关于使用 session.query 通过 SQLAlchemy ORM 更新连接表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆