我试图删除基于查询的记录,其中包括连接到几个别名表。
有问题的表格如下:
class Match(Base):
id_ = Column(Integer, primary_key=True)
tournament_id = Column(Integer, ForeignKey("myschema.tournament.id_"))
round_id = Column(TINYINT, index=True)
player_id_p1 = Column(Integer, ForeignKey("myschema.player.id_"))
player_id_p2 = Column(Integer, ForeignKey("myschema.player.id_"))
p1 = relationship("Player", foreign_keys=[player_id_p1])
p2 = relationship("Player", foreign_keys=[player_id_p2])
class Tournament(Base):
id_ = Column(Integer, primary_key=True)
original_id = Column(Integer, index=True)
tour_id = Column(TINYINT, index=True)
match = relationship("Match", backref="tournament")
class Player(Base):
id_ = Column(Integer, primary_key=True)
original_id = Column(Integer, index=True)
tour_id = Column(TINYINT, index=True)
match = relationship(
'Match',
primaryjoin=("or_(Player.id_ == Match.player_id_p1, Player.id_ == Match.player_id_p2)"),
overlaps="p1, p2",
)
值得一提的是,这些表格是由第三方数据库填充的,该数据库包含两次网球巡回赛的锦标赛,球员和比赛;ATP和WTA。在这个数据库中,每个巡回赛都有单独的锦标赛、球员和比赛表。我将它们导入到数据库中的组合表中,并使用tour_id
字段来标识它们最初来自哪个游/表。我需要能够根据原始锦标赛和球员id从Match
表中删除记录。
我第一次尝试这个查询:
p1 = sa.orm.aliased(Player)
p2 = sa.orm.aliased(Player)
stmt = sa.delete(Match)
stmt = stmt.join(Tournament)
stmt = stmt.join(p1, p1.id_ == Match.player_id_p1)
stmt = stmt.join(p2, p2.id_ == Match.player_id_p2)
stmt = stmt.where(
Tournament.tour_id == tour_id,
Tournament.original_id == 16907,
p1.tour_id == tour_id,
p1.original_id == 79810,
p2.tour_id == tour_id,
p2.original_id == 37136,
Match.round_id == 5,
)
session.execute(stmt)
但是,我得到了错误:
'Delete' object has no attribute 'join'
这个相关的答案说明在1。然后SA将从filter
内获取表,并在SQL中转换为USING
。由此,我用2.0语法构建了以下查询:
p1 = sa.orm.aliased(Player)
p2 = sa.orm.aliased(Player)
stmt = sa.delete(Match)
stmt = stmt.where(
Tournament.tour_id == 0,
Tournament.original_id == 16907,
p1.tour_id == 0,
p1.original_id == 79810
p2.tour_id == 0,
p2.original_id == 37136,
Match.round_id == 5,
)
session.execute(stmt)
然而,我得到了错误:
Exception has occurred: InvalidRequestError (note: full exception trace is shown but execution is paused at: <module>)
Could not evaluate current criteria in Python: "Can't evaluate criteria against alternate class <class 'Tournament'>". Specify 'fetch' or False for the synchronize_session execution option.
我不确定推荐的操作会有什么效果,所以我也调整了解决方案如下:
p1 = sa.orm.aliased(Player)
p2 = sa.orm.aliased(Player)
s_qry = sa.select(Match.id_)
s_qry = s_qry.join(Tournament)
s_qry = s_qry.join(p1, p1.id_ == Match.player_id_p1)
s_qry = s_qry.join(p2, p2.id_ == Match.player_id_p2)
s_qry = s_qry.where(
Tournament.tour_id == tour_id,
Tournament.original_id == 16907,
p1.tour_id == tour_id,
p1.original_id == 79810,
p2.tour_id == tour_id,
p2.original_id == 37136,
Match.round_id == 5,
)
s_qry = s_qry.subquery()
stmt = sa.delete(Match).where(Match.id_.in_(s_qry))
session.execute(stmt)
但是我现在得到错误:
Exception has occurred: InvalidRequestError (note: full exception trace is shown but execution is paused at: <module>)
Could not evaluate current criteria in Python: "Cannot evaluate Select". Specify 'fetch' or False for the synchronize_session execution option.
值得一提的是,在本例中没有符合查询条件的记录。
实现我想要做的事情的最好方法是什么?
当然,SQLAlchemy中的where
子句是一个单语句操作。要考虑多个条件,您要么需要使用and_
操作符,要么将多个.where
调用链接起来。
换句话说,我相信这个可以解决你的问题-
- 使用
and_
操作符:
stmt = stmt.where(and_(Tournament.tour_id == tour_id,
Tournament.original_id == 16907,
p1.tour_id == tour_id,
p1.original_id == 79810,
p2.tour_id == tour_id,
p2.original_id == 37136,
Match.round_id == 5))
- 链接多个
.where
调用:
stmt = stmt.where(Tournament.tour_id == tour_id).
where(Tournament.original_id == 16907).
where(p1.tour_id == tour_id).
where(p1.original_id == 79810).
where(p2.tour_id == tour_id).
where(p2.original_id == 37136).
where(Match.round_id == 5)