初识SQLAlchemy
特点:
SQLAlchemy 是一个功能强大的 Python SQL 工具包和对象关系(ORM)映射框架,旨在提供高效、灵活且便于扩展的数据库交互解决方案。它支持多种数据库,并通过其核心(Core)和 ORM 两个层次为开发者提供不同的抽象级别
- 使用python进行编写
- 一个sql工具包
- 一个orm框架
- 支持常见数据库:sqlserver、mysql、oracle、postgresql、sqllite
下述所展示的操作都以MySQL数据库为例!!!
安装
pip install sqlalchemy
- 如果要使用sqlalchemy操作mysql数据库,还需要安装mysqlclient:
pip install mysqlclient
流程介绍
创建engine
Engine 是 SQLAlchemy 与数据库之间的接口,负责管理数据库连接和执行
python
from sqlalchemy import create_engine
engine = create_engine("mysql+pymysql://user:password@host:port/mydatabase", echo=True)
参数详解:
- user:数据库用户
- password:数据库密码
- host:数据库地址,本地默认为localhost或127.0.0.1
- port:数据库端口,默认为3306
- mydatabase:数据库名称
- echo:是否展示详细数据库操作,True为展示,默认为False
建立连接
python
connection=engine.connect()
查询数据
原始sql查询语句
python
from sqlalchemy import create_engine, text
engine = create_engine("mysql+pymysql://root:root@localhost:3306/orm_study", echo=True)
# 创建一个连接
conn = engine.connect()
# 创建一个查询
query = text("SELECT * FROM users")
# 执行查询
result = conn.execute(query)
# 关闭连接
conn.close()
# 销毁引擎
engine.dispose()

初始版创建表结构
概念信息:
- MetaData: 是 SQLAlchemy 用于存储关于数据库结构信息的对象。它包含了所有表、列、约束等的定义
- Table 和 Column 是定义数据库表和其列的基础组件
示例代码:
python
from sqlalchemy import (
create_engine,
MetaData,
Table,
Column,
Integer,
String,
Date,
)
# 创建一个引擎
engine = create_engine("mysql+pymysql://root:root@localhost:3306/orm_study", echo=True)
# 创建一个元数据
metadata = MetaData()
# 创建一个表
table = Table(
# 表名
"users",
# 元数据(表的描述)
metadata,
# 列
Column("id", Integer, primary_key=True),
Column("name", String(255), nullable=False, unique=True),
Column("birthday", Date, nullable=False),
)
# 创建表
metadata.create_all(engine)
Column 属性详解
- 类型:如 Integer, String, Boolean, DateTime 等,定义列的数据类型。
- 主键(primary_key=True):指定该列为主键。
- 索引(index=True):为该列创建索引,提高查询性能。
- 可空(nullable=False/True):指定该列是否允许为空。
- 默认值(default):为该列设置默认值。
- 自动更新时间(onupdate):在每次更新时自动设置列的值

插入数据(INSERT)
python
# 新增数据
insert_data = table.insert().values(name="张三", birthday="2021-01-01")
# 执行插入
with engine.connect() as conn:
conn.execute(insert_data)
# 提交事务
conn.commit()
table.insert():数据库的插入insert对象
批量插入
python
# 批量插入
insert_data = table.insert().values(
[
{"name": "李四", "birthday": "2021-01-02"},
{"name": "王五", "birthday": "2021-01-03"},
]
)
# 执行插入
with engine.connect() as conn:
conn.execute(insert_data)
# 提交事务
conn.commit()
python
# 批量插入
insert_data = table.insert()
# 执行插入
with engine.connect() as conn:
conn.execute(
insert_data,
[
{"name": "赵六", "birthday": "2021-01-04"},
{"name": "孙七", "birthday": "2021-01-05"},
],
)
# 提交事务
conn.commit()
查询数据(SELECT)
python
with engine.connect() as connect:
query = user_table.select()
query_set = connect.execute(query)
# query_set 迭代器
for row in query_set:
print(row)
print(row.name)

提取数据
python
# 提取所有数据
result = query_set.fetchall()
# 提取一条数据
res_one = query_set.fetchone()
条件查询
python
with engine.connect() as connect:
query = user_table.select().where(user_table.c.birthday > "2021-01-04")
query_set = connect.execute(query)
result = query_set.fetchall()
print(result)
复杂查询:
python
with engine.connect() as connect:
query = (
user_table.select()
.where(user_table.c.birthday > "2021-01-01")
.where(user_table.c.name == "李四")
)
query = user_table.select().where(
or_(
user_table.c.name == "赵六",
and_(user_table.c.birthday > "2021-01-01", user_table.c.id < 7),
)
)
query_set = connect.execute(query)
result = query_set.fetchall()
print(result)
更新数据(UPDATE)
python
with engine.connect() as connect:
update_query = user_table.update().values(birthday="2000-06-09")
update_query = (
user_table.update()
.values(birthday="2000-06-25")
.where(user_table.c.name == "张三")
)
connect.execute(update_query)
connect.commit()
删除数据(DELETE)
python
with engine.connect() as connect:
delete_query = user_table.delete()
delete_query = user_table.delete().where(user_table.c.name == "孙七")
connect.execute(delete_query)
connect.commit()
关联表的定义

python
from sqlalchemy import (
create_engine,
MetaData,
Table,
Column,
Integer,
String,
Date,
ForeignKey,
)
# 创建一个引擎
engine = create_engine("mysql+pymysql://root:root@localhost:3306/orm_study", echo=True)
# 创建一个元数据
metadata = MetaData()
# 部门
department = Table(
"department",
metadata,
Column("id", Integer, primary_key=True),
Column("name", String(255), nullable=False, unique=Table),
)
# 部门
employee = Table(
"employee",
metadata,
Column("id", Integer, primary_key=True),
Column("name", String(255), nullable=False),
Column("department_id", Integer, ForeignKey("department.id"), nullable=False),
Column("birthday", Date, nullable=False),
)
metadata.create_all(engine)
插入数据
python
from db_init import engine, employee, department
with engine.connect() as connect:
connect.execute(department.insert(), [{"name": "HR"}, {"name": "IT"}])
connect.execute(
employee.insert(),
[
{"name": "aaa", "department_id": 1, "birthday": "2000-06-09"},
{"name": "bbb", "department_id": 1, "birthday": "2000-06-10"},
{"name": "ccc", "department_id": 2, "birthday": "2000-06-11"},
{"name": "ddd", "department_id": 2, "birthday": "2000-06-12"},
],
)
connect.commit()
查询数据
python
from db_init import engine, employee, department
from sqlalchemy import select
with engine.connect() as connect:
join_table = employee.join(department, employee.c.department_id == department.c.id)
query = select(join_table).where(department.c.name == "IT")
query = select(employee).select_from(join_table).where(department.c.name == "IT")
print(connect.execute(query).fetchall())
映射类的定义
生成数据库表
python
from sqlalchemy import (
create_engine,
MetaData,
Table,
Column,
Integer,
String,
Date,
ForeignKey,
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
# 创建一个引擎
engine = create_engine("mysql+pymysql://root:root@localhost:3306/orm_study", echo=True)
Base = declarative_base()
class Person(Base):
__tablename__ = "person"
id = Column(Integer, primary_key=True)
name = Column(String(128), unique=True, nullable=False)
birthday = Column(Date, nullable=False)
address = Column(String(255), nullable=True)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
插入数据
单条数据
python
from db_init import Session, Person
session = Session()
per = Person(name="aaa", birthday="2000-06-09", address="北疆")
session.add(per)
session.commit()
多条数据
python
from db_init import Session, Person
session = Session()
# per = Person(name="aaa", birthday="2000-06-09", address="北疆")
per = [
Person(name="bbb", birthday="2000-06-10", address="东疆"),
Person(name="ccc", birthday="2000-06-11", address="南疆"),
]
session.add_all(per)
session.commit()
映射类的查询与修改
查询:
python
from db_init import Session, Person
session = Session()
result = session.query(Person).all()
result = session.query(Person).filter(Person.address == "南疆")
修改:
python
from db_init import Session, Person
session = Session()
# 第一种
per = session.query(Person).filter(Person.id == 1).first()
per.name = "ddd"
# 第二种
per = session.query(Person).filter(Person.id == 2).update({"name": "www"})
session.commit()
优化映射方式
前提:sqlalchemy版本需要大于2.0
python
from sqlalchemy import (
create_engine,
MetaData,
Table,
Column,
Integer,
String,
Date,
ForeignKey,
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Mapped, mapped_column
# 创建一个引擎
engine = create_engine("mysql+pymysql://root:root@localhost:3306/orm_study", echo=True)
Base = declarative_base()
class Customer(Base):
__tablename__ = "customer"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(20))
birthday: Mapped[Date] = mapped_column(Date)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
优化:
python
from datetime import datetime
from sqlalchemy import (
create_engine,
MetaData,
Table,
Column,
Integer,
String,
Date,
ForeignKey,
DateTime,
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Mapped, mapped_column
from typing_extensions import Annotated
# 创建一个引擎
engine = create_engine("mysql+pymysql://root:root@localhost:3306/orm_study", echo=True)
Base = declarative_base()
id_pk = Annotated[int, mapped_column(primary_key=True)]
require_name = Annotated[str, mapped_column(String(20), nullable=False)]
create_time = Annotated[datetime, mapped_column(DateTime, default=datetime.now)]
class Customer(Base):
__tablename__ = "customer"
id: Mapped[id_pk]
name: Mapped[require_name]
birthday: Mapped[Date] = mapped_column(Date)
create_time: Mapped[create_time]
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
一对多ORM操作
初始化表:
python
from datetime import datetime
from sqlalchemy import (
create_engine,
MetaData,
Table,
Column,
Integer,
String,
Date,
ForeignKey,
DateTime,
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Mapped, mapped_column, relationship
from typing_extensions import Annotated
from typing import List
# 创建一个引擎
engine = create_engine("mysql+pymysql://root:root@localhost:3306/orm_study", echo=True)
Base = declarative_base()
id_pk = Annotated[int, mapped_column(primary_key=True)]
require_name = Annotated[str, mapped_column(String(20), nullable=False)]
create_time = Annotated[datetime, mapped_column(DateTime, default=datetime.now)]
class Department(Base):
__tablename__ = "department"
id: Mapped[id_pk]
name: Mapped[require_name]
create_time: Mapped[create_time]
# 反向关联 动态的向employee表中添加department属性
employees: Mapped[List["Employee"]] = relationship(
lazy="select", back_populates="department"
)
def __repr__(self):
return f"<Department(id={self.id}, name={self.name}, create_time={self.create_time})>"
class Employee(Base):
__tablename__ = "employee"
id: Mapped[id_pk]
name: Mapped[require_name]
department_id: Mapped[int] = mapped_column(ForeignKey("department.id"))
create_time: Mapped[create_time]
birthday: Mapped[Date] = mapped_column(Date, nullable=True)
# 反向关联 动态的向department表中添加employees属性
department: Mapped[Department] = relationship(
lazy="select", back_populates="employees"
)
def __repr__(self):
return f"<Employee(id={self.id}, name={self.name}, department_id={self.department_id}, create_time={self.create_time}, birthday={self.birthday})>"
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
新增及查询:
python
from many_db_init import session, Department, Employee
def insert_data():
dep1 = Department(name="开发部")
dep2 = Department(name="销售部")
emp1 = Employee(name="张三", department=dep1)
emp2 = Employee(name="李四", department=dep2)
session.add(emp1)
session.add(emp2)
session.commit()
def select_data():
# 查询部门员工
departments = session.query(Department).filter(Department.id == 3).first()
print(departments.employees)
# 查询员工部门
employees = session.query(Employee).filter(Employee.name == "张三").first()
print(employees.department) # 反向关联
if __name__ == "__main__":
insert_data()
select_data()
多对多ORM操作
初始化数据库表:
python
from datetime import datetime
from sqlalchemy import (
create_engine,
MetaData,
Table,
Column,
Integer,
String,
Date,
ForeignKey,
DateTime,
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Mapped, mapped_column, relationship
from typing_extensions import Annotated
from typing import List
# 创建一个引擎
engine = create_engine("mysql+pymysql://root:root@localhost:3306/orm_study", echo=True)
Base = declarative_base()
id_pk = Annotated[int, mapped_column(primary_key=True)]
require_name = Annotated[str, mapped_column(String(20), nullable=False)]
create_time = Annotated[datetime, mapped_column(DateTime, default=datetime.now)]
assocaiation_table = Table(
"user_role",
Base.metadata,
Column("user_id", Integer, ForeignKey("users.id"), primary_key=True),
Column("role_id", Integer, ForeignKey("roles.id"), primary_key=True),
)
class User(Base):
__tablename__ = "users"
id: Mapped[id_pk]
name: Mapped[require_name]
create_time: Mapped[create_time]
roles: Mapped[List["Role"]] = relationship(
secondary=assocaiation_table, lazy=False, back_populates="users"
)
def __repr__(self):
return f"<User(id={self.id}, name={self.name}, create_time={self.create_time})>"
class Role(Base):
__tablename__ = "roles"
id: Mapped[id_pk]
name: Mapped[require_name]
create_time: Mapped[create_time]
users: Mapped[List["User"]] = relationship(
secondary=assocaiation_table, lazy=False, back_populates="roles"
)
def __repr__(self):
return f"<User(id={self.id}, name={self.name}, create_time={self.create_time})>"
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
新增数据及查询数据
python
from many_to_namy_init import User, Role, session
def insert_records():
role1 = Role(name="admin")
role2 = Role(name="operate")
user1 = User(name="张三")
user2 = User(name="李四")
user3 = User(name="王五")
user1.roles.append(role1)
user1.roles.append(role2)
user2.roles.append(role2)
user3.roles.append(role1)
session.add_all([user1, user2, user3])
session.commit()
def select_records():
user = session.query(User).filter(User.name == "张三").first()
print(user)
print(user.roles)
role = session.query(Role).filter(Role.name == "admin").first()
print(role)
print(role.users)
if __name__ == "__main__":
# insert_records()
select_records()
基于ORM查询
以下述数据表举例:
python
from datetime import datetime, date
from sqlalchemy import (
create_engine,
MetaData,
Table,
Column,
Integer,
String,
Date,
ForeignKey,
DateTime,
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Mapped, mapped_column, relationship
from typing_extensions import Annotated
# 创建一个引擎
engine = create_engine("mysql+pymysql://root:root@localhost:3306/orm_study", echo=True)
Base = declarative_base()
id_pk = Annotated[int, mapped_column(primary_key=True)]
require_name = Annotated[str, mapped_column(String(20), nullable=False)]
create_time = Annotated[datetime, mapped_column(DateTime, default=datetime.now)]
birthday = Annotated[date, mapped_column(Date, nullable=False)]
# 部门
class Department(Base):
__tablename__ = "department"
id: Mapped[id_pk]
name: Mapped[require_name]
create_time: Mapped[create_time]
def __repr__(self):
return f"Department(id={self.id}, name={self.name}, create_time={self.create_time})"
# 员工
class Employee(Base):
__tablename__ = "employee"
id: Mapped[id_pk]
name: Mapped[require_name]
department_id: Mapped[int]
birthday: Mapped[birthday]
create_time: Mapped[create_time]
department: Mapped[Department] = relationship(
Department, back_populates="employees"
)
def __repr__(self):
return f"Employee(id={self.id}, name={self.name}, department_id={self.department_id}, birthday={self.birthday}, create_time={self.create_time})"
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
查询所有部门:
python
def select_one():
# 查询所有部门 先生成一个查询对象
query = select(Department).order_by(Department.name.desc())
# 执行查询
result = session.execute(query)
# 遍历结果
for department in result:
print(department)
查询员工和员工对应的部门(使用别名)
python
def select_one_by_id():
query = select(Department, Employee).join(Employee.department)
result = session.execute(query)
for department in result:
print(department)
# 别名
def select_one_by_alias():
employee_alias = aliased(Employee, name="employee_alias")
department_alias = aliased(Department, name="department_alias")
query = select(department_alias, employee_alias).join(
employee_alias.department.of_type(department_alias)
)
result = session.execute(query)
for department in result:
print(department)
查询多个类中的部分字段(针对单个字段取别名)
python
def select_fields():
query = select(
Department.name.label("department_name"),
Employee.name.label("employee_name"),
).join(Employee.department)
result = session.execute(query)
for department in result:
print(department.department_name, department.employee_name)
def select_fields01():
query = select(
Department.name.label("department_name"),
Employee.name.label("employee_name"),
).join_from(Employee, Department)
result = session.execute(query)
for department in result:
print(department.department_name, department.employee_name)