使用SQLAlchemy select/join关联表遇错误及session数据冗余问题
问题1:正确编写JOIN关联语句的方法
你碰到的AttributeError是因为ORM模型类(Order)本身没有join方法,join操作需要借助SQLAlchemy提供的专用函数或select对象的方法实现。以下是几种可行的写法:
方法1:用join函数配合select_from
from sqlalchemy import join stmt = select(Order.id, Order.product, Customer.name).\ select_from(join(Order, Customer, Order.customer_id == Customer.id))
方法2:直接在select对象上调用join
这种写法更简洁,无需单独指定select_from:
stmt = select(Order.id, Order.product, Customer.name).\ join(Customer, Order.customer_id == Customer.id)
方法3:利用已定义的ORM关系查询
既然已经在模型中定义了relationship关联,可以直接通过关联属性简化查询:
stmt = select(Order.id, Order.product, Customer.name).\ select_from(Order).join(Order.customer)
问题2:Customer表出现冗余数据的原因及解决办法
原因
每次运行脚本时,都会执行以下操作:
Base.metadata.create_all(engine):只会创建不存在的表,不会清空已有数据;session.add_all(customers)+session.commit():每次运行都会向customers表插入新的John、Jane、Bob记录,多次运行就会累积冗余数据(比如运行5次就会生成15条记录)。
解决办法
- 方式1:运行前清空表数据
在插入样本数据前,先清空已有表数据:
Base.metadata.create_all(engine) # 清空Customer和Order表数据 session.query(Customer).delete() session.query(Order).delete() session.commit() # 再插入样本数据 customers = [Customer(name='John'), Customer(name='Jane'), Customer(name='Bob')] session.add_all(customers) session.commit()
- 方式2:检查数据存在性再插入
避免重复插入相同数据,先查询是否已存在对应名称的用户,不存在才插入:
# 处理Customer数据 customer_names = ['John', 'Jane', 'Bob'] for name in customer_names: existing_customer = session.query(Customer).filter_by(name=name).first() if not existing_customer: session.add(Customer(name=name)) session.commit() # 若需避免重复订单,可同理检查Order数据
- 方式3:使用
if_not_exists参数(SQLAlchemy 1.4+)
针对插入操作,可使用insert语句的if_not_exists参数(仅支持PostgreSQL、SQLite 3.35+等数据库):
from sqlalchemy import insert stmt = insert(Customer).values([{'name': 'John'}, {'name': 'Jane'}, {'name': 'Bob'}]).if_not_exists() session.execute(stmt) session.commit()
内容的提问来源于stack exchange,提问作者Pankaj Chowdhury
相关产品推荐
相关产品推荐

