本文参考官方文档,如果错误请指出
1、安装SQLAlchemy并且检查版本
1.1、安装模块 pip3 install SQLAlchemy 1.2、检查版本 >>> import sqlalchemy >>> sqlalchemy.__version__ '1.3.11'
2、数据库连接的创建
from sqlalchemy.engine import create_engine # echo=True表示日志打印出来 engine = create_engine("mysql://mysql_username:mysql_password@IP地址:端口/数据库名字?charset=utf8", encoding='utf-8', echo=False) 注意: 其它数据库配置和更多的create_engine参数方式,请参数官网:https://docs.sqlalchemy.org/en/13/core/engines.html#sqlalchemy.create_engine
3、声明类与数据库表的映射关系
from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() #以User表为例 class User(Base): # 数据库表名 __tablename__ = 'users' # 这个MySQL使用的主键 # id = Column(Integer, primary_key=True, autoincrement=True) # 这个是Oracle使用的主键定义方法,MySQL也通过,推荐使用这个,数据库更换时,可以不用修改代码 id = Column(Integer, Sequence('user_id_seq'), primary_key=True) name = Column(String(30)) fullname = Column(String(30)) nickname = Column(String(30)) def __repr__(self): """命令行运行时,打印对象显示的值调用""" return "" % (self.name, self.fullname, self.nickname)
4、创建数据库连接的会话
from sqlalchemy.engine import create_engine from sqlalchemy.orm import sessionmaker # echo=True表示日志打印出来 engine = create_engine("mysql://django:[email protected]:3306/testDatabase", encoding='utf-8', echo=False) Session = sessionmaker(bind=engine) # 产生会话 Session.configure(bind=engine) # 往Session配置可用的会话引擎 session = Session()
5、数据库数据迁移
# 删除所有表 Base.metadata.drop_all(engine) # 创建所有表 Base.metadata.create_all(engine)
6、简单的单表增删改查示例
#!/usr/bin/env python # -*- coding: utf-8 -*- from sqlalchemy.engine import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, Sequence from sqlalchemy.orm import sessionmaker # echo=True表示日志打印出来 engine = create_engine("mysql://django:[email protected]:3306/day120?charset=utf8", encoding='utf8', echo=False) Base = declarative_base() class User(Base): # 数据库表名 __tablename__ = 'users' # 字段 id = Column(Integer, Sequence('user_id_seq'), primary_key=True) name = Column(String(30)) fullname = Column(String(30)) nickname = Column(String(30)) def __repr__(self): """命令行运行时,打印对象显示的值调用""" return "" % (self.name, self.fullname, self.nickname) def create_all_table(): # 创建所有表 Base.metadata.create_all(engine) def drop_all_table(): # 删除所有表 Base.metadata.drop_all(engine) Session = sessionmaker(bind=engine) # 产生会话 Session.configure(bind=engine) # 往Session配置可用的会话引擎 session = Session() # 1、插入数据 # 1.1、一条数据 ed_user = User(name='阿三', fullname='张三', nickname='张大嘴') session.add(ed_user) session.commit() # 1.2、批量插入数据 session.add_all([ User(name='李一', fullname='li One', nickname='小李子'), User(name='张一', fullname='zhang One', nickname='小张子'), User(name='陈一', fullname='chen One', nickname='小陈子') ]) session.commit() # 2、查询数据 # 2.1、返回对象 user_obj = session.query(User).filter_by(name='阿三').first() print(user_obj) # 2.2、返回列表 user = session.query(User).filter(User.name == '阿三') print('打印出SQL语句', user) # SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.nickname AS users_nickname # FROM users # WHERE users.name = %s print('user.all()', user.all()) # [ ] # 3、删除数据 delete_user_obj = session.query(User).filter(User.name == '张一').delete() session.commit() # 4、修改数据 session.query(User).filter(User.name == '阿三').update({User.nickname: '张大嘴'}) session.commit()
7、SQLAlchemy session.dirty 和session.new的理解
#1、session.new的案例,主要作用:打印出已增加的数据,但是未提交至数据库的数据 # session.add_all([ # User(name='wendy', fullname='Wendy Williams', nickname='windy'), # User(name='mary', fullname='Mary Contrary', nickname='mary'), ]) # # #打印出需要新增加的数据 # print(session.new) """ IdentitySet([, """ #2、session.dirty案例,主要作用:打印出已增加到session中,未提交至数据库,但是在这个过程中又被修改的数据,也叫脏读 ed_user = User(name='ed', fullname='Ed Jones', nickname='edsnickname') session.add(ed_user) #从未提交的数据,查询出数据的对象 our_user = session.query(User).filter_by(name='ed').first() ed_user.nickname = '印度阿三' print(session.dirty) """ IdentitySet([]) ]) """
8、SQLAlchemy session级别的事务回滚
# 从数据库中查询出来一条数据的对象 ed_user = session.query(User).filter(User.name == '阿三').first() ed_user.name = '张三三' # 在内存中修改ed_user对象的名字,因为session里面是指向的内存地址,所以这里一修改,session里面的name也会随着变 fake_user = User(name='李四', fullname='李大四', nickname='李Boss') session.add(fake_user) users = session.query(User).filter(User.name.in_(['张三三', '李四'])).all() print(users) """ [, """ # 回滚到查询没有修改的数据 session.rollback() print(ed_user.name) # 阿三 users = session.query(User).filter(User.name.in_(['阿三', '李四'])).all() print(users) # [] ]
9、SQLAlchemy 查询(Query)示例(官方示例,推荐练习)
############################################################################### # 1、查询结果排序显示出来 users = session.query(User).order_by(User.id) for instance in users: print(instance.id, instance.name, instance.nickname,instance.fullname) """ 1 阿三 张大嘴 张三 2 李一 小李子 li One 20 李一1 小李子 li One 21 张一1 小张子 zhang One 22 陈一1 小陈子 chen One """ ############################################################################### # 2、查询结果,显示指定的列 users = session.query(User.name, User.fullname) for instance in users: print(instance.name, instance.fullname) """ 阿三 张三 李一 li One 李一1 li One 张一1 zhang One 陈一1 chen One """ ############################################################################### # 3、查询所以数据+某一列数据 users = session.query(User, User.name) for instance in users: print(instance.User, instance.name) """阿三 """ ############################################################################### # 4、查询数据结果,并且对列增加标签label,方便python取值 users = session.query(User.name.label('name_label')) for instance in users: print(instance.name_label) """ 阿三 李一 李一1 张一1 陈一1 """ ############################################################################### # 5、查询数据,给数据库User表每一个列增加别名,下面的示例就别名是:user_alias_列名 from sqlalchemy.orm import aliased user_alias = aliased(User, name='user_alias') users = session.query(user_alias, user_alias.name).all() for instance in users: print(instance.user_alias) """李一 李一1 张一1 陈一1 """ ############################################################################### # 7、分页Limit查询 users = session.query(User).order_by()[0:2] for instance in users: print(instance) """ """ ############################################################################### # 8、filter_by使用关键字参数查询 users = session.query(User).filter_by(fullname='li One').all() for instance in users: print(instance) """ """ # 与上面filter_by相同功能示例 users = session.query(User).filter(User.fullname == 'li One').all() for instance in users: print(instance) """ """ ############################################################################### # 9、多层filter()查询,是and关系 users = session.query(User).filter(User.fullname == 'li One').filter(User.name == '李一1').all() for instance in users: print(instance) """ """
10、普通过滤操作符(官方示例,推荐练习)
# 1、相等(==) user_obj = session.query(User).filter(User.name=='阿三').first() print(user_obj) ###################################################################### # 2、不相等(!=) users = session.query(User).filter(User.name != '阿三').all() for instance in users: print(instance) """ """ ##################################################################### # 3、LIKE模糊查询 users = session.query(User).filter(User.nickname.like('%大%')) for instance in users: print(instance) # ##################################################################### # 4、怱略大小写的LIKE模糊查询 users = session.query(User).filter(User.fullname.ilike('%o%')) for instance in users: print(instance) """ """ ##################################################################### # 5、包含(in) # 5.1、通过列表组装单列的查询 users = session.query(User).filter(User.fullname.in_(['chen ene', 'zhang ene'])) for instance in users: print(instance) """ """ # 5.2、通过元组组装,多列混合的查询 from sqlalchemy import tuple_ # in_里面一个元组,对应tuple_条件列数据的过滤 users = session.query(User).filter(tuple_(User.name, User.fullname).in_([('张一1', 'zhang ene'), ('zhang ene','张三')])) for instance in users: print(instance) """ """ ##################################################################### # 6、不包含(not in) users = session.query(User).filter(~User.nickname.in_(['张大嘴','小李子'])) for instance in users: print(instance) """ """ ##################################################################### # 7、过滤行数据不能为空(is not null 或 != none) users = session.query(User).filter(User.nickname != None) for instance in users: print(instance) # 或者 users = session.query(User).filter(User.nickname.isnot(None)) for instance in users: print(instance) """ """ ##################################################################### # 8、且(and) # 方法1、导and_包组装 from sqlalchemy import and_ users = session.query(User).filter(and_(User.name=='阿三',User.fullname=='张三')) # 方法2、默认多个参数就是and关系 users = session.query(User).filter(User.name=='阿三',User.fullname=='张三') # 方法3、多个filter()方法连接 users = session.query(User).filter(User.name == '阿三').filter(User.fullname == '张三') for instance in users: print(instance) """ """ ##################################################################### # 9、或(or) from sqlalchemy import or_ users=session.query(User).filter(or_(User.name=='阿三',User.name=='陈一1')) for instance in users: print(instance) """ """ ##################################################################### # 10、模糊查询(contains) users = session.query(User).filter(User.name.contains('李')) for instance in users: print(instance) """ """
11、SQLAlchemy 查询返回值的介绍(官方示例,推荐了解)
# 1、返回list user_list = session.query(User).all() print(user_list) """ [, """ ######################################################################################### # 2、返回对象 user_obj = session.query(User).first() print(user_obj) """, , , ] """ ######################################################################################### # 3、单独查询一行,如果存在则返回对象,不存在抛出sqlalchemy.orm.exc.NoResultFound异常 user_obj = session.query(User).filter(User.id == 1).one() print(user_obj) """ """ ######################################################################################### # 4、单独查询一行,如果存在则返回对象,不存在返回None user_obj = session.query(User).filter(User.id == '222').scalar() print(user_obj) """ None """
12、SQLAlchemy 手写SQL语句查询
# 1、手写SQL条件查询 from sqlalchemy import text users = session.query(User).filter(text("id>20")).all() for instance in users: print(instance) """""" ################################################################################ # 2、手写SQL+条件组合+params()参数格式化 users = session.query(User).filter(text("name=:name and fullname=:fullname")).params(name="阿三", fullname='张三').all() for instance in users: print(instance) """ """ ################################################################################ # 3、手写完整的SQL语句查询所有列 from sqlalchemy import text users = session.query(User).from_statement(text("SELECT * FROM users where name=:name")).params(name='李一1').all() for instance in users: print(instance) """ """ ################################################################################ # 4、手写完整的SQL语句查询指定的列 from sqlalchemy import text stmt = text("SELECT name, id, nickname ""FROM users where name=:name") stmt = stmt.columns(User.name, User.id, User.nickname) users = session.query(User).from_statement(stmt).params(name='李一').all() for instance in users: print(instance) """ """
13、SQLAlchemy 分组(group by)计数的示例
# 1、分组后,再计数 from sqlalchemy import func users = session.query(func.count(User.nickname), User.nickname).group_by(User.nickname).all() print(users) """ [(1, '小张子'), (2, '小李子'), (1, '小陈子'), (1, '张大嘴')] """ ################################################################################### # 2、计算表中所有列数据行记录总数 from sqlalchemy import func user_count = session.query(func.count('*')).select_from(User).scalar() print(user_count) """ 5 """ ################################################################################### # 3、如果使用主键来计数的话,可以不加select_from(User) from sqlalchemy import func user_count = session.query(func.count(User.id)).scalar() print(user_count) """ 5 """
14、SQLAlchemy 一对多(FK),增删改查示例
#!/usr/bin/env python # -*- coding: utf-8 -*- from sqlalchemy.engine import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, Sequence from sqlalchemy.orm import sessionmaker # echo=True表示日志打印出来 engine = create_engine("mysql://django:[email protected]:3306/databaseName?charset=utf8", encoding='utf8', echo=False) Base = declarative_base() class User(Base): # 数据库表名 __tablename__ = 'users' # 字段 id = Column(Integer, Sequence('user_id_seq'), primary_key=True) name = Column(String(30)) fullname = Column(String(30)) nickname = Column(String(30)) def __repr__(self): """命令行运行时,打印对象显示的值调用""" return "" % (self.name, self.fullname, self.nickname) from sqlalchemy import ForeignKey from sqlalchemy.orm import relationship class Address(Base): __tablename__ = 'addresses' id = Column(Integer, Sequence('user_id_seq'), primary_key=True) email_address = Column(String(30), nullable=False) user_id = Column(Integer, ForeignKey('users.id', ondelete='CASCADE')) # ondelete='CASCADE' : FK级联的配置,如果修改或删除,会清理关联数据,不需要,可以不用填写 # 外键生成在addresses表 user = relationship("User", back_populates="addresses") def __repr__(self): return "" % self.email_address # 给User类增加外键的关系 User.addresses = relationship("Address", order_by=Address.id, back_populates="user", cascade="all, delete-orphan", passive_deletes=True) # cascade="all, delete-orphan",passive_deletes=True,FK级联的配置,不需要,可以不用填写 def create_all_table(): # 创建所有表 Base.metadata.create_all(engine) def drop_all_table(): # 删除所有表 Base.metadata.drop_all(engine) # 数据迁移,创建表 # drop_all_table() # create_all_table() Session = sessionmaker(bind=engine) # 产生会话 Session.configure(bind=engine) # 往Session配置可用的会话引擎 session = Session() ###################################################################################################### # 1、FK数据的增加 jack = User(name='jack', fullname='Jack Bean', nickname='gjffdd') jack.addresses = [ Address(email_address='[email protected]'), Address(email_address='[email protected]') ] session.add(jack) session.commit() ###################################################################################################### # 2、FK数据查询 user_obj = session.query(User).filter(User.name == 'jack').one() print(user_obj) print(user_obj.addresses) """ [, ] """ ###################################################################################################### # 3、FK数据修改 user_obj = session.query(User).filter(User.name == 'jack').one() adress1 = Address(email_address='[email protected]') user_obj.addresses = [adress1, ] session.commit() print(user_obj.addresses) ###################################################################################################### # 4、FK删除数据 session.query(User).filter(User.name == 'jack').delete() session.commit()
15、SQLAlchemy 一对多(FK)为示例,通用的join查询
#!/usr/bin/env python # -*- coding: utf-8 -*- from sqlalchemy.engine import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, Sequence from sqlalchemy.orm import sessionmaker # echo=True表示日志打印出来 engine = create_engine("mysql://django:[email protected]:3306/day120?charset=utf8", encoding='utf8', echo=False) Base = declarative_base() class User(Base): # 数据库表名 __tablename__ = 'users' # 字段 id = Column(Integer, Sequence('user_id_seq'), primary_key=True) name = Column(String(30)) fullname = Column(String(30)) nickname = Column(String(30)) def __repr__(self): """命令行运行时,打印对象显示的值调用""" return "" % (self.name, self.fullname, self.nickname) from sqlalchemy import ForeignKey from sqlalchemy.orm import relationship class Address(Base): __tablename__ = 'addresses' id = Column(Integer, Sequence('user_id_seq'), primary_key=True) email_address = Column(String(30), nullable=False) user_id = Column(Integer, ForeignKey('users.id', ondelete='CASCADE')) # ondelete='CASCADE' : FK级联的配置,如果修改或删除,会清理关联数据,不需要,可以不用填写 # 外键生成在addresses表 user = relationship("User", back_populates="addresses") def __repr__(self): return "" % self.email_address # 给User类增加外键的关系 User.addresses = relationship("Address", order_by=Address.id, back_populates="user", cascade="all, delete-orphan", passive_deletes=True) # cascade="all, delete-orphan",passive_deletes=True,FK级联的配置,不需要,可以不用填写 def create_all_table(): # 创建所有表 Base.metadata.create_all(engine) def drop_all_table(): # 删除所有表 Base.metadata.drop_all(engine) # 数据迁移,创建表 # drop_all_table() # create_all_table() Session = sessionmaker(bind=engine) # 产生会话 Session.configure(bind=engine) # 往Session配置可用的会话引擎 session = Session() # 1、自已建立关联关系查询 result = session.query(User, Address).filter(User.id == Address.user_id).filter( Address.email_address == '[email protected]') print(result) for u, a in result: print(u, a) ################################################################################################### # 2、join # 2.1、join之字符串关联关系,addresses是User,relationship实例名字 result = session.query(User).join('addresses').filter(Address.email_address == '[email protected]').all() # 2.2、join之指明外键关联值,addresses是User,relationship实例名字 result = session.query(User).join(Address,User.addresses).filter(Address.email_address == '[email protected]').all() # 2.3、join之指定从左到右的关系 result = session.query(User).join(User.addresses).filter(Address.email_address == '[email protected]').all() # 2.4、join之明确条件关联 result = session.query(User).join(Address, User.id == Address.user_id).filter(Address.email_address == '[email protected]').all() for instance in result: print(instance) ################################################################################################### # 3、若要控制join关联表的位置,可以使用select_from(table_class),表示放在第一的位置 query = session.query(User, Address).select_from(Address).join(User) print(query) """ SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.nickname AS users_nickname, addresses.id AS addresses_id, addresses.email_address AS addresses_email_address, addresses.user_id AS addresses_user_id FROM addresses(放在内连接的第一个位置) INNER JOIN users ON users.id = addresses.user_id """
16、SQLAlchemy 一对多(FK)为示例,别名的查询,子查询等(少用)
# 1、别名的查询 # 当查询多个表时,如果同一表需要不止一次引用,SQL通常要求该表使用另一个名称进行别名,以便将其与该表的其他事件区分开来。 # 查询最显式地支持使用别名结构。下面我们将两次连接到Address实体,以找到同时具有两个不同电子邮件地址的用户: from sqlalchemy.orm import aliased adalias1 = aliased(Address) adalias2 = aliased(Address) result = session.query(User.name, adalias1.email_address, adalias2.email_address).\ join(adalias1,User.addresses).\ join(adalias2, User.addresses).\ filter(adalias1.email_address == '[email protected]').\ filter(adalias2.email_address == '[email protected]') for username, email1, email2 in result: print(username, email1, email2) # 2、子查询 from sqlalchemy.sql import func stmt = session.query(Address.user_id, func.count('*').\ label('address_count')).\ group_by(Address.user_id).subquery() for u, count in session.query(User, stmt.c.address_count).\ outerjoin(stmt, User.id==stmt.c.user_id).order_by(User.id): print(u, count) #3、从子查询中选择实体,即利用别名查询出结果,再进行join操作 from sqlalchemy.orm import aliased stmt = session.query(Address).filter(Address.email_address != '[email protected]').subquery() adalias = aliased(Address, stmt) for user, address in session.query(User, adalias).join(adalias, User.addresses): print(user, address)
持续更新...