SQLALchemy
本博客参考资料:
[1] SQLALchemy官方文档:地址
[2]《FastApi web开发入门、进阶与实践》
一、SQLALchemy是什么
SQLALchemy是一个ORM(Object-Relational Mapping)库。本质上,ORM是对SQL语句的一种封装,它是对数据库表中列和行操作的一种对象映射。在某些情况下,使用ORM库时甚至不需要了解SQL,只需要通过对表映射出来的实体类模型进行操作就可实现对数据的增、删、改、查操作[2]。
二、为什么需要ORM库
在以往,当我们需要操作数据库时,需要自己去编写增删改查sql语句,并且拼接参数。这样的做法存在以下问题:1. sql语句是字符串,需要人为检查,容易出错。2.重复编写sql语句。3.需要自己将查询结果与python对象映射,麻烦。4.需要掌握sql的语法。这个时候,大家就想有没有一种方法能够解决以上问题呢,不用重复编写sql语句,不用太多的sql语句的基础知识,能够直接操作本地对象的方式去操作数据库中的数据,所以ORM库就出现了。
二、SQLALchemy怎么用
以下内容参考[1]。SQLALchemy目前有2.1、2.0、1.4、1.3几个版本,本文版本是用的2.0。
使用步骤:
1、定义映射类并创建数据表
2、获得session对象
3、构造sql语句
4、执行sql语句
5、获取返回结果
2.1 定义映射类并创建数据表
代码如下:
from sqlalchemy import Column
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
from sqlalchemy import String
from sqlalchemy.orm import declarative_base
from sqlalchemy.orm import relationship# 创建所有模型类的基类,提供 ORM 映射的基础功能。
# 继承 Base 的类会自动注册到 Base.metadata.tables 中,后续可通过 #Base.metadata.create_all() 创建表
Base = declarative_base()class User(Base):# 指定数据库表名为 user_account__tablename__ = "user_account"# 定义主键字段,类型为 Integer,默认自增id = Column(Integer, primary_key=True)name = Column(String(30))fullname = Column(String)# 定义一对多关系(一个用户对应多个地址)addresses = relationship("Address", back_populates="user", cascade="all, delete-orphan")# 调用print(user)时输出以下内容def __repr__(self):return f"User(id={self.id!r}, name={self.name!r}, fullname={self.fullname!r})"class Address(Base):__tablename__ = "address"id = Column(Integer, primary_key=True)email_address = Column(String, nullable=False)user_id = Column(Integer, ForeignKey("user_account.id"), nullable=False)user = relationship("User", back_populates="addresses")def __repr__(self):return f"Address(id={self.id!r}, email_address={self.email_address!r})"
from sqlalchemy import create_engine
# sqlite:///:表示当前目录下的 SQLite 文件,如果没有,则自动创建
# echo=True:输出执行的 SQL 语句(调试用)
# future=True:启用 SQLAlchemy 2.0 兼容模式
# 获取链接到数据库的引擎对象
engine = create_engine("sqlite:///example.db", echo=True, future=True)#其他常用数据库连接方式
mysql_engine = create_engine(# mysql+pymysql:使用 PyMySQL 驱动"mysql+pymysql://user:password@localhost:3306/dbname",# pool_size:连接池大小(默认 5)pool_size=10, # max_overflow:允许临时超出 pool_size 的连接数max_overflow=20,# pool_recycle:连接自动回收时间(秒),避免数据库断开pool_recycle=3600,echo=True
)
postgresql_engine = create_engine("postgresql+psycopg2://user:password@localhost:5432/dbname",isolation_level="REPEATABLE READ",pool_pre_ping=True
)
# 自动创建表,checkfirst为True时,表若存在,则不再创建,否则会报表已存在的错误,默认为True
Base.metadata.create_all(engine, checkfirst = True)
2.2 操作
2.2.1 新增操作
from sqlalchemy.orm import Session# with上下文管理,执行结束后自动释放session
with Session(engine) as session:# 创建User对象spongebob = User(name="spongebob",fullname="Spongebob Squarepants",addresses=[Address(email_address="spongebob@sqlalchemy.org")],)sandy = User(name="sandy",fullname="Sandy Cheeks",addresses=[Address(email_address="sandy@sqlalchemy.org"),Address(email_address="sandy@squirrelpower.org"),],)patrick = User(name="patrick", fullname="Patrick Star")# 批量添加session.add_all([spongebob, sandy, patrick])# 单个添加# session.add(spongebob)# 提交事物session.commit()
2.2.2 查询操作
from sqlalchemy.orm import Sessionwith Session(engine) as session:# 构造sql语句stmt = select(User).where(User.name.in_(["spongebob", "sandy"]))# 执行result = session.execute(stmt)# result.scalars()获取内部数据for user in result.scalars():print(user)# 或者for user in result.scalars().all():print(user)
2.2.3 删除操作
with Session(engine) as session:# 直接按对象删#session.delete(obj1)# 带条件删除stmt = (delete(User).where(User.name == "squidward")# False:完全不同步会话。数据库操作后,会话中的对象可能包含过期数据# 操作前查询数据库获取受影响主键,操作后同步会话中的对象,数据一致性高# 操作前用 Python 评估会话中的对象是否符合条件.execution_options(synchronize_session="fetch"))session.execute(stmt)session.commit()
2.2.4 更新
with Session(engine) as session:stmt = (update(User).where(User.name == "sandy").values(name="spongebob").execution_options(synchronize_session="fetch"))result = session.execute(stmt)session.commit()print(result.rowcount)