python-3.x - SAWarning:评估非映射列表达式
问题描述
这几天一直在测试sqlalchemy,在ORM模式下使用update方法遇到了一些问题。
我基本上想做的是根据对第二个表执行的子查询的结果更新表。
这是一个简化的示例:
from sqlalchemy import create_engine, Column, Integer, Float, Boolean
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session
Base = declarative_base()
engine = create_engine('postgresql+psycopg2://urldb', echo=True)
session = Session(engine)
class User1(Base):
__tablename__ = 'user1'
index = Column(Integer, primary_key=True)
value1 = Column(Float)
value2 = Column(Boolean)
class User2(Base):
__tablename__ = 'user2'
index = Column(Integer, primary_key=True)
value1 = Column(Float)
value2 = Column(Boolean)
try:
User1.__table__.drop(engine)
User2.__table__.drop(engine)
Base.metadata.create_all(engine)
except:
Base.metadata.create_all(engine)
user1 = User1(value1=12, value2=True)
user2 = User1(value1=15, value2=True)
user3 = User1(value1=7, value2=True)
user4 = User2(value1=12, value2=True)
user5 = User2(value1=15, value2=False)
session.add(user1)
session.add(user2)
session.add(user3)
session.add(user4)
session.add(user5)
session.flush()
session.commit()
stmt = session.query(User2).filter(User2.value1 > 12).subquery()
session.query(User1).filter(User1.value1 == stmt.c.value1).update({User1.value2 : stmt.c.value2})
session.commit()
我希望value2
从user2
更新到False
,该代码正确。但是,我收到以下警告消息。据我了解,更新会期望一些类似 ORM 的表达式而不是 stmt.c。但是我看不到如何将我的 stmt 对象转换为 ORM 对象(尝试别名为 User1 但失败了,后来我明白了为什么......)。
有什么想法可以绕过该警告消息吗?提前致谢!
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/sqlalchemy/orm/evaluator.py:71:SAWarning:评估非映射列表达式'%(4357770376 anon)s.value1 ' 到 ORM 实例上;这是一个已弃用的用例。请使用 ORM 评估的 UPDATE / DELETE 表达式中的实际映射列。“更新/删除表达式。” % 子句)/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/sqlalchemy/orm/evaluator.py:71:SAWarning:评估非映射列表达式'%(4357770376 anon) s.value2' 到 ORM 实例上;这是一个已弃用的用例。请使用 ORM 评估的 UPDATE / DELETE 表达式中的实际映射列。“更新/删除表达式。” % 子句)
解决方案
子查询声明不是必需的。您可以直接update from
在 1.4 版上:
from sqlalchemy import update
session.execute(
update(User1).values(
value2=User2.value2
)
.where(User1.value1==User2.value1, User2.value1 > 12)
.execution_options(synchronize_session="fetch") # won't work with 'evaluate'
)
session.commit()
# UPDATE user1 SET value2=(SELECT user2.value2
# FROM user2
# WHERE user1.value1 = user2.value1) WHERE user1.value1 > %(value1_1)s
# RETURNING user1.index
您必须将 设置execution_options
为不引发错误。
另一个选项涉及仅针对值的相关子查询:
from sqlalchemy import select, update
session.execute(
update(User1).values(
value2=select(User2.value2).\
where(User1.value1 == User2.value1).\
scalar_subquery()
)
.where(User1.value1 > 12)
)
session.commit()
# UPDATE user1 SET value2=user2.value2
# FROM user2 WHERE user1.value1 = user2.value1 AND user2.value1 >= %(value1_1)s
# RETURNING user1.index
但随后update where
条件必须适用于User1
。
推荐阅读
- ansible - 在 Ansible 中的扁平数据结构上运行直到循环
- python - 如何根据阈值删除行,但由另一列组织?
- sql - 输入数据时生成时间戳
- graphviz - 使用 foreign_rules_cc 枚举 Bazel 构建的 Graphviz 依赖项
- java - 如何将 firebase 数据库子值保存到共享首选项
- node.js - 错误:DialogFlow 中没有请求意图的处理程序
- git - 我可以从 .git/config 中修剪旧分支吗
- reactjs - 使用 dayjs 禁用银行假日
- express - 我正在尝试从服务器获取 cookie。但是设置cookie不起作用
- javascript - 过滤数组中第一个元素重复两次以上的项