IT评测·应用市场-qidao123.com技术社区

标题: 详细分析Python中的SQLAlchemy库(附Demo) [打印本页]

作者: 东湖之滨    时间: 2024-6-11 12:16
标题: 详细分析Python中的SQLAlchemy库(附Demo)
前言

了解这篇文章的同时保举阅读:
1. 基本知识

一、ORM (对象关系映射)

二、焦点(Core)
SQLAlchemy 的焦点部门提供了一组工具来实行SQL操作,包括创建和实行SQL语句、连接池管理、事务管理等。开发者可以利用焦点部门来实行一些高级的数据库操作,如自定义SQL语句、连接到数据库等。
三、优点

四、缺点:性能开销
只管SQLAlchemy提供了很多便利的功能,但偶然候这些功能可能会带来一定的性能开销。特别是在处理大量数据或需要高性能的场景下,可能需要仔细优化代码以减少性能丧失
五、与其他工具比较
与其他ORM工具的比较:
Django ORMPeeweeSQLObject与Django ORM相比,SQLAlchemy提供了更多的机动性和功能,尤其是在处理复杂数据库操作和跨数据库支持方面

但Django ORM更容易上手,并且与Django框架无缝集成,恰当快速开发和小型项目Peewee 是另一个轻量级的Python ORM工具,相比于SQLAlchemy,它的学习曲线更为平缓,恰当于简朴的数据库操作和小型项目

但Peewee的功能相对较少,不如SQLAlchemy机动SQLObject 是另一个Python ORM库,它的计划更加靠近于Active Record模式,与SQLAlchemy的Data Mapper模式有所不同

但SQLObject的学习曲线较陡,且功能相对较少,通常实用于简朴的数据库操作 2. 基本API


为了让大家更快上手,先学习下下面这个实战项目:
  1. from sqlalchemy import create_engine, Column, Integer, String
  2. from sqlalchemy.orm import sessionmaker
  3. from sqlalchemy.ext.declarative import declarative_base
  4. # 创建引擎
  5. engine = create_engine('mysql+pymysql://root:root@127.0.0.1:3306/easy-admin')
  6. # 创建Session
  7. Session = sessionmaker(bind=engine)
  8. session = Session()
  9. # 定义映射类
  10. Base = declarative_base()
  11. class User(Base):
  12.     __tablename__ = 'manong'
  13.     id = Column(Integer, primary_key=True)
  14.     name = Column(String(255))  # 在这里指定了 name 列的长度为 255
  15.     age = Column(Integer)
  16. # 创建表
  17. Base.metadata.create_all(engine)
  18. # 插入数据
  19. new_user = User(name='yanjiuseng', age=25)
  20. session.add(new_user)
  21. session.commit()
  22. # 查询数据
  23. query = session.query(User).filter(User.age > 18)
  24. result = query.all()
  25. for user in result:
  26.     print(user.name, user.age)
复制代码
终极截图如下:

通过看完整个代码逻辑,带着一些小疑问,深入探究下这些API的利用方式
2.1 create_engine(创建引擎)

create_engine 函数用于创建一个与数据库的连接引擎,该引擎可以实行SQL操作
  1. from sqlalchemy import create_engine
  2. engine = create_engine('mysql+pymysql://username:password@host:port/database')
复制代码
针对里头的参数解释如下:

MySQL 数据库用户名是 user1,密码是 pass123,主机名是 localhost,端标语是 3306,要连接的数据库名称是 my_database,那么连接字符串就应该是:
  1. 'mysql://user1:pass123@localhost:3306/my_database'
复制代码
对于数据库类型常用的:mysql+pymysql,紧张区别在于其利用的数据库驱动程序不同。

再额外补充其他的URL格式:
  1. # MySQL-Python:
  2. mysql+mysqldb://<user>:<password>@<host>:<port>/<dbname>
  3. # pymysql:
  4. mysql+pymysql://<username>:<password>@<host>:<port>/<dbname>?<options>
  5. # MySQL-Connector:
  6. mysql+mysqlconnector://<user>:<password>@<host>:<port>/<dbname>
  7. # cx_Oracle:
  8. oracle+cx_oracle://<user>:<password>@<host>:<port>/<dbname>?key=value&key=value...
复制代码
2.2 sessionmaker(创建session)

用于创建一个 Session 类,该类用于实行 ORM(对象关系映射)操作
紧张作用是创建一个会话工厂,通过工厂可以创建数据库会话对象,用于在代码中实行数据库操作
  1. # 创建Session
  2. Session = sessionmaker(bind=engine)
  3. session = Session()
复制代码
其中sessionmaker的参数如下:

具体示例如下:
  1. from sqlalchemy import create_engine
  2. from sqlalchemy.orm import sessionmaker
  3. # 创建引擎
  4. engine = create_engine('sqlite:///example.db')
  5. # 创建会话工厂
  6. Session = sessionmaker(bind=engine, autocommit=False, autoflush=True)
  7. # 创建会话对象
  8. session = Session()
复制代码
需要注意的点如下:

2.3 declarative_base(定义映射类)

利用 ORM 举行数据库操作的焦点部门之一,涉及到将数据库中的表映射到 Python 中的类,以及定义类属性来表示表的列
一、映射类的定义
通过创建Python 类来表示数据库中的表
该类通常继承自 SQLAlchemy 的 Base 类,而 Base 类是利用 declarative_base() 函数创建的
  1. from sqlalchemy.ext.declarative import declarative_base
  2. Base = declarative_base()
复制代码
二、表的映射
在映射类中定义 __tablename__ 属性,指定该类所映射的数据库表的名称
  1. class User(Base):
  2.     __tablename__ = 'users'
复制代码
三、列的映射
在映射类中定义类属性,来表示表中的列
每个类属性通常都会被定义为 Column 对象,并指定其数据类型以及其他属性
  1. from sqlalchemy import Column, Integer, Stringclass User(Base):
  2.     __tablename__ = 'users'
  3.     id = Column(Integer, primary_key=True)    name = Column(String(255))    age = Column(Integer)
复制代码
对应的属性如下:
属性的寄义:

其他参数:例如长度、唯一性等,用于进一步定义列的属性
2.4 SQL与ORM差异

一、基于 SQL 的查询:
特点:

示例代码:
  1. from sqlalchemy import create_engine, text
  2. # 创建引擎
  3. engine = create_engine('mysql+pymysql://root:root@127.0.0.1:3306/easy-admin')
  4. # 执行 SQL 查询
  5. with engine.connect() as connection:
  6.     result = connection.execute(text("SELECT * FROM manong WHERE age > :age"), {'age': 18})
  7.     for row in result:
  8.         print(row)
复制代码
截图如下:

二、基于ORM查询

  1. from sqlalchemy import create_engine, Column, Integer, Stringfrom sqlalchemy.orm import sessionmakerfrom sqlalchemy.ext.declarative import declarative_base# 创建引擎engine = create_engine('mysql+pymysql://root:root@127.0.0.1:3306/easy-admin')# 创建Session
  2. Session = sessionmaker(bind=engine)
  3. session = Session()
  4. # 定义映射类Base = declarative_base()class User(Base):    __tablename__ = 'manong'    id = Column(Integer, primary_key=True)    name = Column(String(255))  # 在这里指定了 name 列的长度为 255    age = Column(Integer)result = session.query(User).filter(User.age > 18).all()for user in result:    print(user.name, user.age)
复制代码
区别的方式在于:

3. ORM CRUD

对于基本的SQL查询,需要编写SQL语句,此处偏向实战类,所以详细补充ORM CRUD的的基本知识
前半部门代码如下:
  1. from sqlalchemy import create_engine, Column, Integer, Stringfrom sqlalchemy.orm import sessionmakerfrom sqlalchemy.ext.declarative import declarative_base# 创建引擎engine = create_engine('mysql+pymysql://root:root@127.0.0.1:3306/easy-admin')# 创建Session
  2. Session = sessionmaker(bind=engine)
  3. session = Session()
  4. # 定义映射类Base = declarative_base()class User(Base):    __tablename__ = 'manong'    id = Column(Integer, primary_key=True)    name = Column(String(255))  # 在这里指定了 name 列的长度为 255    age = Column(Integer)# 创建表Base.metadata.create_all(engine)
复制代码
3.1 增长(C)


  1. user = User(name='AA', age=30)
  2. session.add(user)
  3. session.commit()
复制代码

  1. users = [User(name='BB', age=30), User(name='CC', age=25)]
  2. session.add_all(users)
  3. session.commit()
复制代码
3.2 查找(R)


  1. all_users = session.query(User).all()
复制代码

  1. # # 查询数据
  2. result = session.query(User).filter(User.age > 18).all()
  3. for user in result:
  4.     print(user.name, user.age)
复制代码

  1. user = session.query(User).filter_by(name='Alice').first()
复制代码
3.3 更新(U)


  1. user = session.query(User).filter_by(name='Alice').first()
  2. user.age = 35session.commit()
复制代码

  1. session.query(User).filter(User.age < 30).update({'age': 30})
  2. session.commit()
复制代码
3.4 删除(D)


  1. user = session.query(User).filter_by(name='Alice').first()
  2. session.delete(user)session.commit()
复制代码

  1. session.query(User).filter(User.age > 30).delete()
  2. session.commit()
复制代码
4. 彩蛋

4.1 建表Bug

建表的过程中如果语句如下:
  1. class Manong(Base):
  2.     __tablename__ = 'manong'
  3.     id = Column(Integer)
  4.     name = Column(String)
复制代码
报错信息如下: sqlalchemy.exc.CompileError: (in table 'manong', column 'name'): VARCHAR requires a length on dialect mysql
紧张问题如下:
在 MySQL 中,VARCHAR 类型的列必须指定长度,即字符的最大数量。
需要为表中的 VARCHAR 类型的列指定长度
将其代码修改为:
  1. from sqlalchemy import Column, Integer, Stringfrom sqlalchemy.ext.declarative import declarative_base
  2. Base = declarative_base()
  3. class Manong(Base):    __tablename__ = 'manong'    id = Column(Integer, primary_key=True)    name = Column(String(255))  # 在这里指定了 name 列的长度为 255# 继续定义其他列和表布局
复制代码
如果不是建表,可以省略字段长度
4.2 filter 和 filter_by


以下为简易Demo,方便理解:
  1. # 使用 filter 方法
  2. from sqlalchemy.orm import sessionmaker
  3. Session = sessionmaker(bind=engine)
  4. session = Session()
  5. # 查询名字为 Alice 的记录
  6. alice_records = session.query(User).filter(User.name == 'Alice').all()
  7. # 查询年龄大于等于 25 岁的记录
  8. older_users = session.query(User).filter(User.age >= 25).all()
  9. # 使用 filter_by 方法
  10. # 查询名字为 Alice 的记录
  11. alice_records = session.query(User).filter_by(name='Alice').all()
复制代码
filter 的组合查询: (这个在实战中比较常用!!!)
通过连续调用来实现多个条件的组合查询,大概利用AND 条件连接多个条件
  1. # 使用 filter 连续添加条件查询
  2. # 查询名字为 Alice 且年龄大于等于 25 岁的记录
  3. alice_older_records = session.query(User).filter(User.name == 'Alice').filter(User.age >= 25).all()
复制代码
大概如下:
  1. from sqlalchemy import and_
  2. # 使用 and_ 函数连接两个条件
  3. alice_older_records = session.query(User).filter(and_(User.name == 'Alice', User.age >= 25)).all()
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/) Powered by Discuz! X3.4