我正在尝试使用SQLAlchemy实现以下MySQL查询。有问题的表是嵌套集层次结构。
UPDATE category
JOIN
(
SELECT
node.cat_id,
(COUNT(parent.cat_id) - 1) AS depth
FROM category AS node, category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY node.cat_id
) AS depths
ON category.cat_id = depths.cat_id
SET category.depth = depths.depth
这很好用。
这是我开始拔头发的地方:
from sqlalchemy.orm import aliased
from sqlalchemy import func
from myapp.db import db
node = aliased(Category)
parent = aliased(Category)
stmt = db.session.query(node.cat_id,
func.count(parent.cat_id).label('depth_'))\
.filter(node.lft.between(parent.lft, parent.rgt))\
.group_by(node.cat_id).subquery()
db.session.query(Category,
stmt.c.cat_id,
stmt.c.depth_)\
.outerjoin(stmt,
Category.cat_id == stmt.c.cat_id)\
.update({Category.depth: stmt.c.depth_},
synchronize_session='fetch')
......我得到InvalidRequestError: This operation requires only one Table or entity be specified as the target
。在我看来,Category.depth
充分指定了目标,但当然SQLAlchemy胜过我的想法。
难住了。有什么建议?感谢。
答案 0 :(得分:1)
我知道这个问题已有5年历史了,但是今天我偶然发现了这个问题。我的回答可能对其他人有用。我知道我的解决方案不是完美的解决方案,但是我没有更好的方法。
我只需要将最后一行更改为:
db.session.query(Category)\
.outerjoin(stmt,
Category.cat_id == stmt.c.cat_id)\
.update({Category.depth: stmt.c.depth_},
synchronize_session='fetch')
然后,您必须提交更改:
db.session.commit()
这会发出以下警告:
SAWarning:将未映射的列表达式'...'评估到ORM上 实例这是一个已弃用的用例。请利用 ORM评估的UPDATE / DELETE表达式中的实际映射列。
“更新/删除表达式。” %条款
要摆脱它,我在这篇文章中使用了解决方案:Turn off a warning in sqlalchemy
注意:由于某些原因,别名在SQLAlchemy更新语句中不起作用。