如何使用SqlModel删除符合指定条件的所有行?
SqlModel批量删除符合条件记录的优化方案
问题背景
SqlModel官方文档中展示了用.one()或.first()获取单条记录后执行删除的方法,示例代码如下:
def delete_heroes(): with Session(engine) as session: statement = select(Hero).where(Hero.name == "Spider-Youngster") results = session.exec(statement) hero = results.one() print("Hero: ", hero) session.delete(hero) session.commit()
但当需要删除所有符合条件的记录时,直接用.all()获取列表后调用session.delete()会报错:sqlalchemy.orm.exc.UnmappedInstanceError: Class 'builtins.list' is not mapped,错误代码如下:
def delete_heroes(): with Session(engine) as session: statement = select(Hero).where(Hero.name == "Spider-Youngster") results = session.exec(statement) hero = results.all() print("Hero: ", hero) session.delete(hero) session.commit()
目前通过循环遍历结果逐一删除可以实现需求,但希望找到无需循环的实现方式。
无需循环的解决方案
方法1:直接执行批量删除语句(推荐)
直接构造DELETE语句在数据库层面执行,无需将对象加载到内存,效率更高,也不需要循环:
from sqlmodel import delete def delete_heroes(): with Session(engine) as session: # 构造批量删除语句 statement = delete(Hero).where(Hero.name == "Spider-Youngster") # 执行删除 result = session.exec(statement) # 提交事务 session.commit() # 获取删除的记录数 print(f"成功删除 {result.rowcount} 条记录")
方法2:批量删除已加载的对象
如果业务需要先加载对象(比如要读取对象属性、触发ORM事件),可以使用session.bulk_delete_objects()方法,直接传入对象列表完成批量删除:
def delete_heroes(): with Session(engine) as session: statement = select(Hero).where(Hero.name == "Spider-Youngster") # 加载所有符合条件的对象 heroes = session.exec(statement).all() print("待删除的英雄: ", heroes) # 批量删除对象列表 session.bulk_delete_objects(heroes) session.commit()
注意:
bulk_delete_objects()不会触发ORM的before_delete/after_delete等事件,适合纯批量删除场景。
补充:修正原循环代码的问题
原循环代码存在一个隐性错误:调用results.all()后,结果集已经被完全消费,后续for result in results不会遍历到任何数据。正确的写法应该遍历存储结果的变量:
def delete_heroes(): with Session(engine) as session: statement = select(Hero).where(Hero.name == "Spider-Youngster") heroes = session.exec(statement).all() print("Hero: ", heroes) for hero in heroes: session.delete(hero) session.commit()
内容的提问来源于stack exchange,提问作者RaamEE
相关产品推荐
相关产品推荐

