找回密码
 会员注册
查看: 31|回复: 0

详细分析Python中的SQLAlchemy库(附Demo)

[复制链接]

2万

主题

0

回帖

6万

积分

超级版主

积分
64080
发表于 2024-9-13 11:56:08 | 显示全部楼层 |阅读模式
目录前言1.基本知识2.基本API2.1create_engine(创建引擎)2.2sessionmaker(创建session)2.3declarative_base(定义映射类)2.4SQL与ORM差异3.ORMCRUD3.1增加(C)3.2查找(R)3.3更新(U)3.4删除(D)4.彩蛋4.1建表Bug4.2filter和filter_by前言了解这篇文章的同时推荐阅读:详细讲解Python连接Mysql的基本操作java框架零基础从入门到精通的学习路线附开源项目面经等(超全)1.基本知识一、ORM(对象关系映射):SQLAlchemy是PythonSQL工具包和对象关系映射器(ORM),允许Python开发者在应用程序中使用SQL来交互,而无需处理数据库的具体细节提供一个高层的抽象层,允许开发者通过Python类和对象来表示数据库中的表和行,从而使得数据库操作更加方便和灵活二、核心(Core):SQLAlchemy的核心部分提供了一组工具来执行SQL操作,包括创建和执行SQL语句、连接池管理、事务管理等。开发者可以使用核心部分来执行一些高级的数据库操作,如自定义SQL语句、连接到数据库等。三、优点:灵活性:多种不同的方式来与数据库交互,包括使用核心部分执行原始SQL语句、使用ORM进行对象关系映射、以及使用表达式语言构建SQL查询等功能丰富:许多功能丰富的工具和API,满足各种不同的数据库操作需求ORM支持:SQLAlchemy的ORM工具允许开发者使用Python类来代表数据库中的表和行,从而使得数据库操作更加Pythonic和易于理解ORM工具提供了一种高级的抽象,隐藏了底层数据库操作的细节,使得开发者可以更专注于业务逻辑的实现跨数据库支持:支持多种不同的数据库后端,包括MySQL、PostgreSQL、SQLite等活跃的社区:SQLAlchemy有一个活跃的社区,提供了大量的文档、教程和示例代码,使得开发者可以更容易地学习和使用这个工具包四、缺点:性能开销尽管SQLAlchemy提供了许多便利的功能,但有时候这些功能可能会带来一定的性能开销。特别是在处理大量数据或需要高性能的场景下,可能需要仔细优化代码以减少性能损失五、与其他工具比较:与其他ORM工具的比较:DjangoORMPeeweeSQLObject与DjangoORM相比,SQLAlchemy提供了更多的灵活性和功能,尤其是在处理复杂数据库操作和跨数据库支持方面但DjangoORM更容易上手,并且与Django框架无缝集成,适合快速开发和小型项目Peewee是另一个轻量级的PythonORM工具,相比于SQLAlchemy,它的学习曲线更为平缓,适合于简单的数据库操作和小型项目但Peewee的功能相对较少,不如SQLAlchemy灵活SQLObject是另一个PythonORM库,它的设计更加接近于ActiveRecord模式,与SQLAlchemy的DataMapper模式有所不同但SQLObject的学习曲线较陡,且功能相对较少,通常适用于简单的数据库操作2.基本API安装库:pipinstallSQLAlchemy验证是否安装成功:python-c"importsqlalchemy;print(sqlalchemy.__version__)"或者pipshowsqlalchemy为了让大家更快上手,先学习下下面这个实战项目:fromsqlalchemyimportcreate_engine,Column,Integer,Stringfromsqlalchemy.ormimportsessionmakerfromsqlalchemy.ext.declarativeimportdeclarative_base#创建引擎engine=create_engine('mysql+pymysql://root:root@127.0.0.1:3306/easy-admin')#创建SessionSession=sessionmaker(bind=engine)session=Session()#定义映射类Base=declarative_base()classUser(Base):__tablename__='manong'id=Column(Integer,primary_key=True)name=Column(String(255))#在这里指定了name列的长度为255age=Column(Integer)#创建表Base.metadata.create_all(engine)#插入数据new_user=User(name='yanjiuseng',age=25)session.add(new_user)session.commit()#查询数据query=session.query(User).filter(User.age>18)result=query.all()foruserinresult:print(user.name,user.age)123456789101112131415161718192021222324252627282930313233343536最终截图如下:通过看完整个代码逻辑,带着一些小疑问,深入探讨下这些API的使用方式2.1create_engine(创建引擎)create_engine函数用于创建一个与数据库的连接引擎,该引擎可以执行SQL操作fromsqlalchemyimportcreate_engineengine=create_engine('mysql+pymysql://username:password@host:port/database')123针对里头的参数解释如下:mysql:指定数据库类型,这里是MySQL数据库username:数据库用户名password:数据库密码host:数据库主机名或IP地址port:数据库端口号,默认是MySQL的端口号3306database:要连接的数据库名称MySQL数据库用户名是user1,密码是pass123,主机名是localhost,端口号是3306,要连接的数据库名称是my_database,那么连接字符串就应该是:'mysql://user1:pass123@localhost:3306/my_database'1'运行运行对于数据库类型常用的:mysql+pymysql,主要区别在于其使用的数据库驱动程序不同。mysql+pymysql:(更简单地安装和使用,可以选择使用pymysql)指定使用PyMySQL作为连接MySQL数据库的驱动程序,PyMySQL是一个纯Python实现的MySQL客户端库,兼容Python数据库API规范2.0,可以在Python中直接使用mysql:(对性能要求比较高,可以选择使用mysql并配合MySQLdb或者mysqlclient)没有指定具体的数据库驱动程序,使用默认的MySQL客户端库,一般情况下会使用MySQLdb或者mysqlclient再额外补充其他的URL格式:#MySQL-Python:mysql+mysqldb://: @: /#pymysql:mysql+pymysql://: @: /?#MySQL-Connector:mysql+mysqlconnector://: @: /#cx_Oracleracle+cx_oracle://: @: /?key=value&key=value...12345678910112.2sessionmaker(创建session)用于创建一个Session类,该类用于执行ORM(对象关系映射)操作主要作用是创建一个会话工厂,通过工厂可以创建数据库会话对象,用于在代码中执行数据库操作#创建SessionSession=sessionmaker(bind=engine)session=Session()123其中sessionmaker的参数如下:bind:要绑定到的数据库引擎,通常是一个create_engine函数返回的Engine对象class_:可选参数,指定要创建的会话类,默认为Session类autocommit:是否自动提交事务,默认为Falseautoflush:是否自动刷新会话,默认为Trueexpire_on_commit:在提交事务时是否自动使对象过期,默认为Trueinfo:一个字典,用于指定会话的其他配置信息具体示例如下:fromsqlalchemyimportcreate_enginefromsqlalchemy.ormimportsessionmaker#创建引擎engine=create_engine('sqlite:///example.db')#创建会话工厂Session=sessionmaker(bind=engine,autocommit=False,autoflush=True)#创建会话对象session=Session()1234567891011需要注意的点如下:在使用会话对象执行数据库操作后,一般需要调用commit方法提交事务,或者调用rollback方法回滚事务。在会话对象的作用域结束时,通常需要调用close方法关闭会话,释放数据库连接资源。2.3declarative_base(定义映射类)使用ORM进行数据库操作的核心部分之一,涉及到将数据库中的表映射到Python中的类,以及定义类属性来表示表的列一、映射类的定义:通过创建Python类来表示数据库中的表该类通常继承自SQLAlchemy的Base类,而Base类是使用declarative_base()函数创建的fromsqlalchemy.ext.declarativeimportdeclarative_baseBase=declarative_base()123二、表的映射:在映射类中定义__tablename__属性,指定该类所映射的数据库表的名称classUser(Base):__tablename__='users'12三、列的映射:在映射类中定义类属性,来表示表中的列每个类属性通常都会被定义为Column对象,并指定其数据类型以及其他属性fromsqlalchemyimportColumn,Integer,StringclassUser(Base):__tablename__='users'id=Column(Integer,primary_key=True)name=Column(String(255))age=Column(Integer)12345678对应的属性如下:属性的含义:Column:表示一个数据库表的列Integer、String等数据类型:表示列的数据类型primary_key=True:指定该列为主键其他参数:例如长度、唯一性等,用于进一步定义列的属性2.4SQL与ORM差异一、基于SQL的查询:特点:原始的SQL查询语句,手动编写SQL语句来执行数据库操作。于执行复杂的查询、跨表查询或性能要求较高的场景示例代码:fromsqlalchemyimportcreate_engine,text#创建引擎engine=create_engine('mysql+pymysql://root:root@127.0.0.1:3306/easy-admin')#执行SQL查询withengine.connect()asconnection:result=connection.execute(text("SELECT*FROMmanongWHEREage>:age"),{'age':18})forrowinresult:print(row)12345678910截图如下:二、基于ORM查询:操作对象来执行数据库操作,而不需要编写原始的SQL语句提供了更加Pythonic和面向对象的接口,使得代码更加清晰和易于维护fromsqlalchemyimportcreate_engine,Column,Integer,Stringfromsqlalchemy.ormimportsessionmakerfromsqlalchemy.ext.declarativeimportdeclarative_base#创建引擎engine=create_engine('mysql+pymysql://root:root@127.0.0.1:3306/easy-admin')#创建SessionSession=sessionmaker(bind=engine)session=Session()#定义映射类Base=declarative_base()classUser(Base):__tablename__='manong'id=Column(Integer,primary_key=True)name=Column(String(255))#在这里指定了name列的长度为255age=Column(Integer)result=session.query(User).filter(User.age>18).all()foruserinresult:print(user.name,user.age)12345678910111213141516171819202122232425区别的方式在于:实现方式:基于SQL的查询直接使用原始的SQL语句,而基于ORM的查询则是通过ORM工具来执行数据库操作编写方式:基于SQL的查询需要开发者手动编写SQL语句,而基于ORM的查询则是通过操作对象来执行数据库操作,不需要编写原始的SQL语句灵活性:基于SQL的查询更加灵活,可以执行复杂的原始SQL查询,而基于ORM的查询提供了更加Pythonic和面向对象的接口,使得代码更加清晰和易于维护3.ORMCRUD对于基本的SQL查询,需要编写SQL语句,此处偏向实战类,所以详细补充ORMCRUD的的基本知识前半部分代码如下:fromsqlalchemyimportcreate_engine,Column,Integer,Stringfromsqlalchemy.ormimportsessionmakerfromsqlalchemy.ext.declarativeimportdeclarative_base#创建引擎engine=create_engine('mysql+pymysql://root:root@127.0.0.1:3306/easy-admin')#创建SessionSession=sessionmaker(bind=engine)session=Session()#定义映射类Base=declarative_base()classUser(Base):__tablename__='manong'id=Column(Integer,primary_key=True)name=Column(String(255))#在这里指定了name列的长度为255age=Column(Integer)#创建表Base.metadata.create_all(engine)1234567891011121314151617181920212223243.1增加(C)添加单个对象:将新对象添加到数据库中user=User(name='AA',age=30)session.add(user)session.commit()123添加多个对象:将多个新对象批量添加到数据库中users=[User(name='BB',age=30),User(name='CC',age=25)]session.add_all(users)session.commit()1233.2查找(R)查询所有对象:从数据库中检索所有对象all_users=session.query(User).all()1根据条件查询:根据指定条件过滤对象##查询数据result=session.query(User).filter(User.age>18).all()foruserinresult:print(user.name,user.age)1234查询单个对象:从数据库中检索满足条件的单个对象user=session.query(User).filter_by(name='Alice').first()13.3更新(U)更新单个对象:修改数据库中的现有对象user=session.query(User).filter_by(name='Alice').first()user.age=35session.commit()123批量更新:使用update()方法批量更新满足条件的对象session.query(User).filter(User.age30).delete()session.commit()124.彩蛋4.1建表Bug建表的过程中如果语句如下:classManong(Base):__tablename__='manong'id=Column(Integer)name=Column(String)12345报错信息如下:sqlalchemy.exc.CompileErrorintable'manong',column'name'):VARCHARrequiresalengthondialectmysql主要问题如下:在MySQL中,VARCHAR类型的列必须指定长度,即字符的最大数量。需要为表中的VARCHAR类型的列指定长度将其代码修改为:fromsqlalchemyimportColumn,Integer,Stringfromsqlalchemy.ext.declarativeimportdeclarative_baseBase=declarative_base()classManong(Base):__tablename__='manong'id=Column(Integer,primary_key=True)name=Column(String(255))#在这里指定了name列的长度为255#继续定义其他列和表结构123456789101112如果不是建表,可以省略字段长度4.2filter和filter_byfilter方法使用类名和属性名来构建查询条件,比较通常使用==,也可以使用其他比较操作符如>,=,=25).all()#使用filter_by方法#查询名字为Alice的记录alice_records=session.query(User).filter_by(name='Alice').all()123456789101112131415filter的组合查询:(这个在实战中比较常用!!!)通过连续调用来实现多个条件的组合查询,或者使用AND条件连接多个条件#使用filter连续添加条件查询#查询名字为Alice且年龄大于等于25岁的记录alice_older_records=session.query(User).filter(User.name=='Alice').filter(User.age>=25).all()123或者如下:fromsqlalchemyimportand_#使用and_函数连接两个条件alice_older_records=session.query(User).filter(and_(User.name=='Alice',User.age>=25)).all()1234
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-26 11:33 , Processed in 1.201943 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表