一、SQLAlchemy简单介绍
SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。
SQLAlchemy“采用简单的Python语言,为高效和高性能的数据库访问设计,实现了完整的企业级持久模型”。SQLAlchemy的理念是,SQL数据库的量级和性能重要于对象集合;而对象集合的抽象又重要于表和行。因此,SQLAlchmey采用了类似于Java里Hibernate的数据映射模型,而不是其他ORM框架采用的Active Record模型。不过,Elixir和declarative等可选插件可以让用户使用声明语法。
什么是ORM框架?
对象关系映射(英语:Object Relation Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。
ORM方法论基于三个核心原则:
简单:以最基本的形式建模数据。
传达性:数据库结构被任何人都能理解的语言文档化。
精确性:基于数据模型创建正确标准化的结构。
典型地,建模者通过收集来自那些熟悉应用程序但不熟练的数据建模者的人的信息开发信息模型
SQLAlchemy本身无法操作数据库,其必须以来pymsql等第三方插件,Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作,如:
Dialect:用于和数据API进行交互,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作,如:
数据库类型+数据库驱动名称://用户名:口令(密码)@机器IP地址:端口(即数据库端口)/数据库名
MySQL-Python mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname> pymysql mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>] MySQL-Connector mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname> cx_Oracle oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...] 更多详见:http://docs.sqlalchemy.org/en/latest/dialects/index.html
注意【2.7版本使用mysqldb,3.5版本使用pymysql,安装可选择源码安装或则pip】
二、底层处理
使用 Engine/ConnectionPooling/Dialect 进行数据库操作,Engine使用ConnectionPooling连接数据库,然后再通过Dialect执行SQL语句。
from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://root:123@127.0.0.1:3306/t1", max_overflow=5) # 执行SQL # cur = engine.execute( # "INSERT INTO hosts (host, color_id) VALUES (‘1.1.1.22‘, 3)" # ) # 新插入行自增ID # cur.lastrowid # 执行SQL # cur = engine.execute( # "INSERT INTO hosts (host, color_id) VALUES(%s, %s)",[(‘1.1.1.22‘, 3),(‘1.1.1.221‘, 3),] # ) # 执行SQL # cur = engine.execute( # "INSERT INTO hosts (host, color_id) VALUES (%(host)s, %(color_id)s)", # host=‘1.1.1.99‘, color_id=3 # ) # 执行SQL # cur = engine.execute(‘select * from hosts‘) # 获取第一行数据 # cur.fetchone() # 获取第n行数据 # cur.fetchmany(3) # 获取所有数据 # cur.fetchall()
三、ORM功能使用
使用 ORM/Schema Type/SQL Expression Language/Engine/ConnectionPooling/Dialect 所有组件对数据进行操作。根据类创建对象,对象转换成SQL,执行SQL。
1)创建单表
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author:lcj #导入sqlalchemy模块 from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index,Table from sqlalchemy.orm import sessionmaker, relationship #链接数据库:用户名密码:/root:123123,库名:LCJ engine = create_engine("mysql+pymysql://root:123123@192.168.1.152:3306/LCJ", max_overflow=5) #生成sqlORM基类 Base = declarative_base() # 单表 class Lcj(Base): #继承基类中所有子类方法 __tablename__ = ‘xiaoluo‘ #创建表名:test #设置nid为主键ID,并且设置id为自增就加,Column:表示列 nid = Column(Integer, primary_key=True,autoincrement=True) #设置name列,字符类型为字符串,长度为32字节 name = Column(String(32)) #创建单表只能通过基类中所有子类按照数据库中对应的数据创建表信息 # def init_db(): Base.metadata.create_all(engine) ##创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例 Session = sessionmaker(engine) session = Session #获取session,然后把对象添加到session,最厚提交并关闭,Session对象可视为当前数据库连接
注意:
create_engine() ---->创建一个数据库引擎
mysql+mysqldb:指定了使用Mysql-Python来链接,格式:用户名+密码@数据库IP地址+端口/库名,max_verflow:设置链接数
chatrset:设置数据连接时使用的字符集(可省约)=utf-8
字段:Column
索引:Index
表:Table
2)创建一对多
!/usr/bin/env python # -*- coding:utf-8 -*- # Author:lcj from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index from sqlalchemy.orm import sessionmaker, relationship from sqlalchemy import create_engine #sqlalchemy 功能:要么创建表结果或删除,不能修改表结构 #创建引擎 engine = create_engine("mysql+pymysql://root:123123@192.168.1.152:3306/test", max_overflow=5) #root:123123mysql用户名和密码test:库名 #默认写法,创建一个基类
Base = declarative_base()# 创建一对多表 class ff(Base): __tablename__ = ‘alex‘ #创建表名:alex nid = Column(Integer, primary_key=True)#创建整型的主键ID caption = Column(String(32),default=‘red‘,unique=True) #String类型,默认红色,唯一值 class Person(Base): __tablename__ = ‘jack‘#创建表名:jack nid = Column(Integer,primary_key=True) #设置主键 name = Column(String(32),index=True, nullable=True) #设置索引 favor_id = Column(Integer,ForeignKey("alex.nid")) #alex.nid:需要与alex关联 # 与生成表结构无关,仅用于查询方便 favor = relationship(‘alex‘,backref=‘pers‘) #执行此句,默认找Base所有子类,根据类的结构在数据库中生成对应的数据表信息
Base.metadata.create_all(engine)
isouter:左链接
join关联默认表示 inner join :内链接
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author:lcj from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index from sqlalchemy.orm import sessionmaker, relationship engine = create_engine("mysql+pymysql://root:123123@192.168.1.152:3306/test", max_overflow=5) Base = declarative_base() # 单表 class Test(Base): __tablename__ = ‘test‘ nid = Column(Integer, primary_key=True,autoincrement=True) name = Column(String(32)) # 一对多 class Group(Base): __tablename__ = ‘group‘ nid = Column(Integer, primary_key=True,autoincrement=True) caption = Column(String(32)) class User(Base): __tablename__ = ‘user‘ nid = Column(Integer, primary_key=True,autoincrement=True) username = Column(String(32)) group_id = Column(Integer, ForeignKey(‘group.nid‘)) #__repr__方法表示:__repr__返回什么数据,则在对象输出中也显示响应的数据,否则只是输出对象地址,对象输出:111行 def __repr__(self): temp = "%s - %s: %s" %(self.nid, self.username, self.group_id) return temp def init_db(): Base.metadata.create_all(engine) # def drop_db(): # Base.metadata.drop_all(engine) init_db() #通过函数调用Base中所有子类生成表 #Seesion:创建于数据库会话连接 Seesion =sessionmaker(bind=engine) session = Seesion() #向group表中插入多条数据 # session.add(Group(caption=‘dba‘)) # session.add(Group(caption=‘ddd‘)) # #向user同时插入多条数据 # session.add_all([ # User(username=‘lcj1‘,group_id=1), # User(username=‘lcj2‘,group_id=2), # User(username=‘lcj3‘,group_id=2) # ]) # session.commit() #获取用户:User表中username==lcj1所有的数据/ ret = session.query(User).filter(User.username==‘lcj1‘).all() print(ret) # user表中没有rper方法:则ret对象输出[<__main__.User object at 0x000000000370AEF0>] # [1 - lcj1: 1] print("----------------------------------") #获取User表中所有数据 # ret = session.query(User).all() # print(ret) # [1 - lcj1: 1, 2 - lcj2: 2, 3 - lcj3: 2] # print(ret[0]) #获取第一个数据 # 1 - lcj1: 1 print("----------------------------") #获取user表中nid=1的元素 # obj = ret[0] # print(obj.nid) # print(obj.username) # print(obj.group_id) # 1 # lcj1 # 1 #输出执行sql语句 sql = session.query(User,Group).join(Group) print(sql) # SELECT "user".nid AS user_nid, "user".username AS user_username, "user".group_id AS user_group_id, "group".nid AS group_nid, "group".caption AS group_caption # FROM "user" JOIN "group" ON "group".nid = "user".group_id print("----------------------------------------------") sql = session.query(User,Group).join(Group,isouter=True) #isouter:左链接 print(sql) # SELECT "user".nid AS user_nid, "user".username AS user_username, "user".group_id AS user_group_id, "group".nid AS group_nid, "group".caption AS group_caption # FROM "user" LEFT OUTER JOIN "group" ON "group".nid = "user".group_id #输出User表和Group表关联的所有数据,默认join关联表示 inner join :内链接 ret =session.query(User).join(Group).all() print(ret) print("--------------------------------------") ret =session.query(User).join(Group,isouter=True).all() print(ret)
注意:
1.left join(左联接):
eft join是以A表的记录为基础的,A[主表]可以看成左表,B[副表]可以看成右表,left join是以左表为准的.
换句话说,左表(A)的记录将会全部表示出来,而右表(B)只会显示符合搜索条件的记录(例子中为: a.id = b.id).
B表记录不足的地方均为NULL.
2.right join(右联接):
和left join的结果刚好相反,这次是以右表(B) [主表]为基础的,A[主表]表不足的地方用NULL填充.
3.inner join(相等联接或内联接):
inner join并不以谁为基础,它只显示符合条件的记录.
在创建多表联合查询时,此两句同时存在,才会创建两表之间的关系列
group_id = Column(Integer, ForeignKey(‘group.nid‘))
group = relationship("Group", backref=‘uuu‘)#此时uuu表示USER表中所有的用户,uuu虚拟存在内存
#!/usr/bin/env python # -*- coding:utf-8 -*- # Author:lcj from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index from sqlalchemy.orm import sessionmaker, relationship engine = create_engine("mysql+pymysql://root:123123@192.168.1.152:3306/test", max_overflow=5) #创建Base基类 Base = declarative_base() # 单表 class Test(Base): __tablename__ = ‘test‘ nid = Column(Integer, primary_key=True,autoincrement=True) name = Column(String(32)) # 一对多 class Group(Base): __tablename__ = ‘group‘ nid = Column(Integer, primary_key=True,autoincrement=True) caption = Column(String(32)) class User(Base): __tablename__ = ‘user‘ nid = Column(Integer, primary_key=True, autoincrement=True) username = Column(String(32)) group_id = Column(Integer, ForeignKey(‘group.nid‘)) #relationship:建立表与表之间的关系方法,此时:建立User表和Group表之间关系,并建立两表关系映射关系uuu group = relationship("Group", backref=‘uuu‘)#此时uuu表示USER表中所有的用户,uuu虚拟存在内存 #__repr__方法表示:__repr__返回什么数据,则在对象输出中也显示响应的数据,否则只是输出对象地址,对象输出:111行 def __repr__(self): temp = "%s - %s: %s" % (self.nid, self.username, self.group_id) return temp def init_db(): Base.metadata.create_all(engine) # def drop_db(): # Base.metadata.drop_all(engine) init_db() #通过函数调用Base中所有子类生成表 #Seesion:创建于数据库会话连接 Seesion =sessionmaker(bind=engine) session = Seesion() #打印链表操作默认链接方式: sql = session.query(User,Group).join(Group) print(sql) print("-----------------------------------------------------------") ret = session.query(User.username,Group.caption).join(Group,).all() print(ret) #打印链表操作默认链接方式:isouter左链接 sql = session.query(User,Group).join(Group,isouter=True) #isouter:左链接 print(sql) print("-----------------------------------------------------------") #原始方式查询 ret = session.query(User.username,Group.caption).join(Group,isouter=True).all() print(ret) #正向查询:即表示通过已存在的列查找其他表中存在数据 ret = session.query(User).all() for obj in ret: # obj代指user表的没一行数据 # obj.group代指group对象, # print(obj.nid, obj.username, obj.group_id, obj.group, obj.group.nid, obj.group.caption) print("-------------------------------------------------------") #原始方式: obj = session.query(Group).filter(Group.caption==‘dba‘).first() print(obj) print("==================================================") #新方式:反向查询,即通过两表所建立的uuu关系列,获取两表用外键关联的所有数据 obj = session.query(Group).filter(Group.caption==‘ddd‘).first() print(obj.nid) # 2 #循环获取Group表中caption==‘ddd‘对应的nid,并且只取第一个 print(obj.caption) #ddd # group_id为group表的外键,并通过在user表建立【group = relationship("Group", backref=‘uuu‘)】关系列uuu, # 此时uuu表示USER表中所有的用户,通过uuu列可获取Group表中caption==ddd对应在user表中关联的username数据 print(obj.uuu) #[2 - lcj2: 2, 3 - lcj3: 2] sql= session.query(Group).filter(Group.caption==‘dba‘) print(sql) # SELECT "group".nid AS group_nid, "group".caption AS group_caption # FROM "group" # WHERE "group".caption = :caption_1 sql = session.query(Group).get(1) print(sql) # < __main__.Group object at 0x0000000003F886A0 >
关系图表:
3)创建多对多
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index from sqlalchemy.orm import sessionmaker, relationship from sqlalchemy import create_engine #sqlalchemy 功能:要么创建表结果或删除,不能修改表结构 #创建引擎 engine = create_engine("mysql+pymysql://root:123123@192.168.1.152:3306/test", max_overflow=5) #root:123123mysql用户名和密码test:库名 #默认写法,创建一个基类 Base = declarative_base() # 创建多对多表 class ServerToGroup(Base): __tablename__ = ‘servertogroup‘ #servertogroup:此表是关系表,表示group表和server表关联 nid = Column(Integer, primary_key=True, autoincrement=True) server_id = Column(Integer, ForeignKey(‘server.id‘)) group_id = Column(Integer, ForeignKey(‘group.id‘)) group = relationship("Group", backref=‘s2g‘) server = relationship("Server", backref=‘s2g‘) class Group(Base): __tablename__ = ‘group‘ id = Column(Integer, primary_key=True) name = Column(String(64), unique=True, nullable=False) port = Column(Integer, default=22) # group = relationship(‘Group‘,secondary=ServerToGroup,backref=‘host_list‘) class Server(Base): __tablename__ = ‘server‘ id = Column(Integer, primary_key=True, autoincrement=True) hostname = Column(String(64), unique=True, nullable=False) #执行此句,默认找Base所有子类,根据类的结构在数据库中生成对应的数据表信息 Base.metadata.create_all(engine) Base.metadata.drop_all(engine) #删除所有表
增加数据:
#链接 Session = sessionmaker(bind=engine) session= Session() #对数据库进行操作 # obj= Users(id = 2,name=‘lcj‘,extra=2) #创建对象 # session.add(obj)#对通过对象对server表进行插入数据 # session.add_all(obj) #对表中所有字段进行添加多条数据 session.add_all([ #对通过对象对server表进行插入数据 Users(id =3, name=‘lcj1‘,extra=3), Users(id =4, name=‘lcj2‘,extra=4), ]) session.commit() #获取session,然后把对象添加到session,最后提交并关闭。Session对象可视为当前数据库连接。
mysql> select * from xiaoluo; +----+------+-------+ | id | name | extra | +----+------+-------+ | 1 | lcj | NULL | | 2 | lcj | 2 | | 3 | lcj1 | 3 | | 4 | lcj2 | 4 | +----+------+-------+
删除数据:
#删除ID》2的数据 session.query(Users).filter(Users.id>2).delete() session.commit() #获取session,然后把对象添加到session,最后提交并关闭。Session对象可视为当前数据库连接。 mysql> select * from xiaoluo; +----+------+-------+ | id | name | extra | +----+------+-------+ | 1 | lcj | NULL | | 2 | lcj | 2 | +----+------+-------+ 2 rows in set (0.00 sec)
修改数据:
session.query(Users).filter(Users.id > 2).update({"name" : "099"}) session.query(Users).filter(Users.id > 2).update({Users.name: Users.name + "099"}, synchronize_session=False) session.query(Users).filter(Users.id > 2).update({"num": Users.num + 1}, synchronize_session="evaluate") session.commit()
链接 Session = sessionmaker(bind=engine) session= Session() #对数据库进行操作 # obj= Users(id = 2,name=‘lcj‘,extra=2) #创建对象 # session.add(obj)#对通过对象对server表进行插入数据 # session.add_all(obj) #对表中所有字段进行添加多条数据 session.add_all([ #对通过对象对server表进行插入数据 Users(id =3, name=‘lcj1‘,extra=3), Users(id =4, name=‘lcj2‘,extra=4), Users(id =5, name=‘lcj3‘,extra=5), Users(id =6, name=‘lcj3‘,extra=6), ]) #删除ID》2的数据 # session.query(Users).filter(Users.id>2).delete() session.commit() #获取session,然后把对象添加到session,最后提交并关闭。Session对象可视为当前数据库连接 #修改数据之前表中原始数据 mysql> select * from xiaoluo; +----+------+-------+ | id | name | extra | +----+------+-------+ | 1 | lcj | NULL | | 2 | lcj | 2 | | 4 | lcj2 | 4 | | 3 | lcj1 | 3 | | 5 | lcj3 | 5 | | 6 | lcj3 | 6 | +----+------+-------+ 6 rows in set (0.00 sec) #修改数据,将ID等于2的name从lcj改成alex session.query(Users).filter(Users.id==2).update({‘name‘ : ‘alex‘}) session.commit() #获取session,然后把对象添加到session,最后提交并关闭。Session对象可视为当前数据库连接。 #改之后结果: mysql> select * from xiaoluo; +----+------+-------+ | id | name | extra | +----+------+-------+ | 1 | lcj | NULL | | 2 | alex | 2 | | 4 | lcj2 | 4 | | 3 | lcj1 | 3 | | 5 | lcj3 | 5 | | 6 | lcj3 | 6 | +----+------+-------+ 6 rows in set (0.00 sec) #其他方法 #修改数据,将id>2的所有name改成zhangxiao # session.query(Users).filter(Users.id==2).update({‘name‘ : ‘alex‘}) session.query(Users).filter(Users.id>2).update({‘name‘:‘zhangxiao‘}) session.commit() #获取session,然后把对象添加到session,最后提交并关闭。Session对象可视为当前数据库连接。 #改之后结果: mysql> select * from xiaoluo; +----+-----------+-------+ | id | name | extra | +----+-----------+-------+ | 1 | lcj | NULL | | 2 | alex | 2 | | 4 | zhangxiao | 4 | | 3 | zhangxiao | 3 | | 5 | zhangxiao | 5 | | 6 | zhangxiao | 6 | +----+-----------+-------+ 6 rows in set (0.00 sec)
查询数据:
#方式一:查询表中所有的值 ret = session.query(Users).all() print(ret) session.commit() #获取session,然后把对象添加到session,最后提交并关闭。Session对象可视为当前数据库连接。 #[<__main__.Users object at 0x0000000003F424E0>, <__main__.Users object at 0x0000000003F425C0>, <__main__.Users object at 0x0000000003F42630>, <__main__.Users object at 0x0000000003F42198>, <__main__.Users object at 0x0000000003F423C8>, <__main__.Users object at 0x0000000003F42940>] #方式二:查询表中指定字段 #查询表中name=alex的字段 ret = session.query(Users).filter_by(name=‘alex‘).all() print(ret) #[<__main__.Users object at 0x0000000003F43320>] session.commit() #获取session,然后把对象添加到session,最后提交并关闭。Session对象可视为当前数据库连接 #方式三:查询表所有的name和id字段 ret = session.query(Users.name,Users.id).all() print(ret) session.commit() #获取session,然后把对象添加到session,最后提交并关闭。Session对象可视为当前数据库连接。 # [(‘lcj‘, 1), (‘alex‘, 2), (‘zhangxiao‘, 3), (‘zhangxiao‘, 4), (‘zhangxiao‘, 5), (‘zhangxiao‘, 6)] #方式四:在表中查出name=zhangxiao的第一个字段 ret = session.query(Users).filter_by(name=‘zhangxiao‘).first() print(ret) session.commit() #获取session,然后把对象添加到session,最后提交并关闭。Session对象可视为当前数据库连接。 # <__main__.Users object at 0x00000000037476A0> #方式五:遍历字段 ret = session.query(Users).filter_by(name=‘zhangxiao‘).all() print(ret) for i in ret: #遍历出多个name=zhangxiao的字段 print(i.name,i.id) session.commit() # [<__main__.Users object at 0x0000000003F428D0>, <__main__.Users object at 0x0000000003F42320>, <__main__.Users object at 0x0000000003F42390>, <__main__.Users object at 0x0000000003F426D8>] # zhangxiao 3 # zhangxiao 4 # zhangxiao 5 # zhangxiao 6 #方式6 #输出表中以name进行排序 ret = session.query(Users).order_by(Users.name).all() print(ret) for i in ret: #遍历出多个name=zhangxiao的字段 print(i.name,i.id) session.commit() # [<__main__.Users object at 0x0000000003FC1898>, <__main__.Users object at 0x0000000003FC1908>, <__main__.Users object at 0x0000000003FC1358>, <__main__.Users object at 0x0000000003FC1278>, <__main__.Users object at 0x0000000003FC16D8>, <__main__.Users object at 0x0000000003FC19B0>] # alex 2 # lcj 1 # zhangxiao 4 # zhangxiao 3 # zhangxiao 5 # zhangxiao 6 #方式七:输出sql语句 q = session.query(Users) print(q) #数出sql语句 session.commit() # SELECT xiaoluo.id AS xiaoluo_id, xiaoluo.name AS xiaoluo_name, xiaoluo.extra AS xiaoluo_extra # FROM xiaoluo
其他用法:
# 条件 ret = session.query(Users).filter_by(name=‘alex‘).all() ret = session.query(Users).filter(Users.id > 1, Users.name == ‘eric‘).all() ret = session.query(Users).filter(Users.id.between(1, 3), Users.name == ‘eric‘).all() ret = session.query(Users).filter(Users.id.in_([1,3,4])).all() ret = session.query(Users).filter(~Users.id.in_([1,3,4])).all() ret = session.query(Users).filter(Users.id.in_(session.query(Users.id).filter_by(name=‘eric‘))).all() from sqlalchemy import and_, or_ ret = session.query(Users).filter(and_(Users.id > 3, Users.name == ‘eric‘)).all() ret = session.query(Users).filter(or_(Users.id < 2, Users.name == ‘eric‘)).all() ret = session.query(Users).filter( or_( Users.id < 2, and_(Users.name == ‘eric‘, Users.id > 3), Users.extra != "" )).all() # 通配符 ret = session.query(Users).filter(Users.name.like(‘e%‘)).all() ret = session.query(Users).filter(~Users.name.like(‘e%‘)).all() # 限制 ret = session.query(Users)[1:2] # 排序 ret = session.query(Users).order_by(Users.name.desc()).all() ret = session.query(Users).order_by(Users.name.desc(), Users.id.asc()).all() # 分组 from sqlalchemy.sql import func ret = session.query(Users).group_by(Users.extra).all() ret = session.query( func.max(Users.id), func.sum(Users.id), func.min(Users.id)).group_by(Users.name).all() ret = session.query( func.max(Users.id), func.sum(Users.id), func.min(Users.id)).group_by(Users.name).having(func.min(Users.id) >2).all() # 连表 ret = session.query(Users, Favor).filter(Users.id == Favor.nid).all() ret = session.query(Person).join(Favor).all() ret = session.query(Person).join(Favor, isouter=True).all() # 组合 q1 = session.query(Users.name).filter(Users.id > 2) q2 = session.query(Favor.caption).filter(Favor.nid < 2) ret = q1.union(q2).all() q1 = session.query(Users.name).filter(Users.id > 2) q2 = session.query(Favor.caption).filter(Favor.nid < 2) ret = q1.union_all(q2).all()
其他用法
完善中
左链接右链接