组合查询将两张表用笛卡尔积的效果显现出来:
from sqlalchemy.orm import scoped_session from sqlalchemy.orm import sessionmaker # 导入引擎,模型表等 from models import * # 通过Session绑定引擎和数据库建立关系 Session = sessionmaker(bind=engine) # 创建链接池,使用session即可为当前线程拿出一个链接对象。内部采用threading.local进行隔离 session = scoped_session(Session) # 必须用filter,获取全部也是,不可以使用all因为他会返回一个list,list不具备union_all # 使用filter返回的对象是:<class 'sqlalchemy.orm.query.Query'> # 并且query中必须单拿某一个字段,如果不指定字段就直接返回对象 s = session.query(Students.name).filter() t = session.query(Teachers.name).filter() c = session.query(Classes.name).filter() ret = s.union_all(t).union_all(c).all() # 用列表显示 print(ret) # [('学生01',), ('学生02',), ('老师01',), ('老师02',), ('老师03',), ('一年级一班',), ('一年级二班',)] # 提交 session.commit() # 关闭链接 session.close() 连表查询使用join进行连表查询:
from sqlalchemy.orm import scoped_session from sqlalchemy.orm import sessionmaker # 导入引擎,模型表等 from models import * # 通过Session绑定引擎和数据库建立关系 Session = sessionmaker(bind=engine) # 创建链接池,使用session即可为当前线程拿出一个链接对象。内部采用threading.local进行隔离 session = scoped_session(Session) # 手动指定条件查询 result = session.query(Students.name, Classes.name).filter(Students.id == Classes.id).all() for i in result: print(i) # 连接查询,同上,内部自动指定 Students.fk_class == Classes.id 的条件 result = session.query(Students.name, Classes.name).join(Classes).all() # 相当于:result = session.query(Students.name,Classes.name).join(Classes, Students.fk_class == Classes.id).all() for i in result: print(i) # 左链接查询,即使有同学没有班级也拿出来 result = session.query(Students.name, Classes.name).join(Classes, isouter=True).all() for i in result: print(i) # 如果想查看有哪些班级没有同学,就换一个位置 result = session.query(Students.name, Classes.name).join(Students, isouter=True).all() for i in result: print(i) # 三表查询,需要自己指定条件 result = session.query(Teachers.name, Classes.name, TeachersM2mClasses.id) \ .join(Teachers, TeachersM2mClasses.teacher_id == Teachers.id) \ .join(Classes, TeachersM2mClasses.class_id == Classes.id) \ .filter() # 查看原生语句 print(result) for i in result: print(i) # 提交 session.commit() # 关闭链接 session.close() 正反查询上面是使用join进行的连表查询,其实也可以使用逻辑字段relationship查询。
from sqlalchemy.orm import scoped_session from sqlalchemy.orm import sessionmaker # 导入引擎,模型表等 from models import * # 通过Session绑定引擎和数据库建立关系 Session = sessionmaker(bind=engine) # 创建链接池,使用session即可为当前线程拿出一个链接对象。内部采用threading.local进行隔离 session = scoped_session(Session) # 正向:查看第一个老师都在哪些班级(通过逻辑字段的名字) result = session.query(Teachers).first() # result.re_class是一个列表,存了有关该老师所在的班级 <class 'sqlalchemy.orm.collections.InstrumentedList'> for class_obj in result.re_class: # 查看其所有的班级 print(class_obj.name) # 反向:查看第一个班级下都有哪些老师,都有哪些学生(通过逻辑字段中的backref参数进行反向查询) result = session.query(Classes).first() # 看老师 for teacher_obj in result.teachers: print(teacher_obj.name) # 看学生 for student_obj in result.students: print(student_obj.name) # 提交 session.commit() # 关闭链接 session.close() 正反方法
使用逻辑字段relationship可拥有一些方法执行增删改。
由于逻辑字段是一个类似列表的存在,所以列表的方法都能用。
print(type(老师对象.班级列表)) # <class 'sqlalchemy.orm.collections.InstrumentedList'>比如使用extend方法增加老师的班级:
# 给老师增加班级 result = session.query(Teachers).first() # extend方法: result.re_class.extend([ Classes(name="三年级一班",), Classes(name="三年级二班",), ])使用remove方法删除老师的班级:
# 减少老师所在的班级 result = session.query(Teachers).first() # 待删除的班级对象,集合查找比较快 delete_class_set = { session.query(Classes).filter_by(id=7).first(), session.query(Classes).filter_by(id=8).first(), } # 循换老师所在的班级 # remove方法: for class_obj in result.re_class: if class_obj in delete_class_set: result.re_class.remove(class_obj)使用clear清空老师所对应的班级:
# 拿出一个老师 result = session.query(Teachers).first() result.re_class.clear() 原生SQL 查看SQL命令