黑洞来咯
89.71MB · 2026-02-15
想象一下,在编写 Web 应用或数据处理程序时,如果需要直接使用 SQL 语句与数据库交互,就像在高速公路上骑着自行车——虽然能够到达目的地,但不仅效率低下,而且随时可能因为写错一个关键字而导致整个程序崩溃。SQLAlchemy 正是为解决这个痛点而生的 Python 数据库工具包。
SQLAlchemy 是 Python 中最流行的 SQL 工具包和对象关系映射器(ORM),它在 Python 生态系统中占据着不可替代的地位。简单来说,SQLAlchemy 提供了两种使用方式:
SQLAlchemy 的核心价值在于:
安装 SQLAlchemy 非常简单,使用 pip 即可:
# 安装最新稳定版
pip install SQLAlchemy
# 安装指定版本(如 2.0.x)
pip install SQLAlchemy==2.0.45
# 安装预发布版本(用于测试新特性)
pip install --pre SQLAlchemy
如果需要支持特定数据库,还需要安装对应的 DBAPI(以 PostgreSQL 为例):
pip install psycopg2-binary # PostgreSQL
pip install pymysql # MySQL
pip install cx-Oracle # Oracle
让我们通过一个完整的 "Hello World" 示例来快速了解 SQLAlchemy 的基本用法:
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import DeclarativeBase, Session
# 1. 定义基础类
class Base(DeclarativeBase):
pass
# 2. 定义模型(映射到数据库表)
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50), nullable=False)
email = Column(String(100), unique=True)
# 3. 创建数据库引擎(使用 SQLite)
engine = create_engine('sqlite:///example.db', echo=True)
# 4. 创建表结构
Base.metadata.create_all(engine)
# 5. 插入数据
with Session(engine) as session:
# 创建新用户对象
new_user = User(name='张三', email='zhangsan@example.com')
# 添加到会话
session.add(new_user)
# 提交到数据库
session.commit()
# 查询数据
users = session.query(User).all()
for user in users:
print(f'ID: {user.id}, 姓名: {user.name}, 邮箱: {user.email}')
create_engine 用于建立数据库连接,Column 等用于定义表结构Base 类,这是所有 ORM 模型的基类User 类,它对应数据库中的 users 表。__tablename__ 指定表名,各个 Column 定义表字段sqlite:///example.db 表示使用 SQLite 数据库(文件名:example.db),echo=True 会打印执行的 SQL 语句,便于调试运行结果:
ID: 1, 姓名: 张三, 邮箱: zhangsan@example.com
常见安装问题:
pip install -i SQLAlchemySQLAlchemy 的架构清晰,核心概念主要包括以下几个部分:
Engine 是 SQLAlchemy 的心脏,负责管理与数据库的连接池和实际通信。
from sqlalchemy import create_engine
# 创建引擎
engine = create_engine('postgresql://user:password@localhost/mydatabase')
# 引擎本身不直接连接数据库,而是在需要时从连接池中获取连接
关键点:
Session 是 ORM 的核心,实现了工作单元(Unit of Work)模式。它负责:
from sqlalchemy.orm import Session
# 创建会话
with Session(engine) as session:
# 会话内部的工作
pass
模型(或称为映射类)是数据库表的 Python 表示。每个模型类都继承自 DeclarativeBase(SQLAlchemy 2.0+)或使用 declarative_base(旧版本)。
graph TD
A[Engine 引擎] -->|管理连接池| B[Connection 连接]
B -->|执行SQL| C[Database 数据库]
A -->|创建| D[Session 会话]
D -->|操作| E[Model 模型]
D -->|跟踪状态变化| F[Unit of Work 工作单元]
F -->|提交事务| B
E -->|映射到| G[Table 表结构]
G -->|包含| H[Column 列]
H -->|可关联| I[Relationship 关系]
style A fill:#e1f5ff
style D fill:#fff4e1
style E fill:#ffe1e1
概念间的关系:
工作流程:
让我们通过一个完整的实战项目——博客文章管理系统——来综合运用 SQLAlchemy 的核心功能。
我们需要实现一个简单的博客系统,具备以下功能:
我们将使用 SQLAlchemy 的 ORM 功能:
Author(作者)和 Article(文章)relationship 建立一对多关系Session 完成数据持久化和查询from sqlalchemy import create_engine, Column, Integer, String, DateTime, ForeignKey, func
from sqlalchemy.orm import DeclarativeBase, Session, relationship
from datetime import datetime
# 1. 定义基础类
class Base(DeclarativeBase):
pass
# 2. 定义 Author 模型(作者表)
class Author(Base):
__tablename__ = 'authors'
id = Column(Integer, primary_key=True)
username = Column(String(50), nullable=False, unique=True)
email = Column(String(100), nullable=False, unique=True)
# 一对多关系:一个作者可以有多篇文章
articles = relationship('Article', back_populates='author', cascade='all, delete-orphan')
# 3. 定义 Article 模型(文章表)
class Article(Base):
__tablename__ = 'articles'
id = Column(Integer, primary_key=True)
title = Column(String(200), nullable=False)
content = Column(String, nullable=False)
publish_time = Column(DateTime, default=func.now())
author_id = Column(Integer, ForeignKey('authors.id'), nullable=False)
# 反向关系:文章属于一个作者
author = relationship('Author', back_populates='articles')
# 4. 创建数据库引擎
engine = create_engine('sqlite:///blog.db', echo=False)
# 5. 创建表结构
Base.metadata.create_all(engine)
# 6. 实战操作:完整的 CRUD 流程
with Session(engine) as session:
# ========== 创建(Create)==========
print("=== 创建作者和文章 ===")
# 创建作者
author1 = Author(username='小明', email='xiaoming@example.com')
author2 = Author(username='小红', email='xiaohong@example.com')
# 创建文章并关联作者
article1 = Article(
title='SQLAlchemy 入门指南',
content='SQLAlchemy 是一个强大的 Python ORM 框架...',
author=author1
)
article2 = Article(
title='Python 高级编程技巧',
content='装饰器、生成器、上下文管理器...',
author=author1
)
article3 = Article(
title='Web 开发最佳实践',
content='RESTful API 设计原则...',
author=author2
)
# 批量添加到会话
session.add_all([author1, author2, article1, article2, article3])
session.commit()
print(f" 已创建 2 位作者和 3 篇文章n")
# ========== 读取(Read)==========
print("=== 查询文章 ===")
# 查询所有文章
all_articles = session.query(Article).all()
for article in all_articles:
print(f"文章: {article.title}")
print(f" 作者: {article.author.username}")
print(f" 发布时间: {article.publish_time}")
print()
# 查询某位作者的所有文章
print("=== 查询小明的所有文章 ===")
ming_articles = session.query(Article).join(Author).filter(Author.username == '小明').all()
for article in ming_articles:
print(f"- {article.title}")
print()
# ========== 更新(Update)==========
print("=== 更新文章 ===")
# 找到要更新的文章
article_to_update = session.query(Article).filter(Article.title == 'SQLAlchemy 入门指南').first()
article_to_update.title = 'SQLAlchemy 2.0 完全指南(更新版)'
article_to_update.content = '本文将深入介绍 SQLAlchemy 2.0 的新特性...'
session.commit()
print(f" 已更新文章标题为:{article_to_update.title}n")
# ========== 删除(Delete)==========
print("=== 删除文章 ===")
# 删除某篇文章
article_to_delete = session.query(Article).filter(Article.title == 'Web 开发最佳实践').first()
session.delete(article_to_delete)
session.commit()
print(" 已删除文章:Web 开发最佳实践n")
# ========== 最终统计 ==========
print("=== 最终统计 ===")
print(f"作者数量: {session.query(Author).count()}")
print(f"文章数量: {session.query(Article).count()}")
print(f"小明的文章数: {len(ming_articles)}")
blog_demo.pypip install SQLAlchemypython blog_demo.py=== 创建作者和文章 ===
已创建 2 位作者和 3 篇文章
=== 查询文章 ===
文章: SQLAlchemy 入门指南
作者: 小明
发布时间: 2026-02-03 11:05:58
文章: Python 高级编程技巧
作者: 小明
发布时间: 2026-02-03 11:05:58
文章: Web 开发最佳实践
作者: 小红
发布时间: 2026-02-03 11:05:58
=== 查询小明的所有文章 ===
- SQLAlchemy 入门指南
- Python 高级编程技巧
=== 更新文章 ===
已更新文章标题为:SQLAlchemy 2.0 完全指南(更新版)
=== 删除文章 ===
已删除文章:Web 开发最佳实践
=== 最终统计 ===
作者数量: 2
文章数量: 2
小明的文章数: 2
relationship 定义模型间的关系,back_populates 实现双向关联cascade='all, delete-orphan' 表示删除作者时自动删除其所有文章default=func.now() 使用数据库函数自动填充发布时间ForeignKey 确保数据完整性session.query().join().filter() 构建复杂查询# 错误做法
with Session(engine) as session:
new_user = User(name='张三')
session.add(new_user)
# 忘记 session.commit(),数据不会写入数据库!
# 正确做法
with Session(engine) as session:
new_user = User(name='张三')
session.add(new_user)
session.commit() # 必须提交!
原因:SQLAlchemy 默认开启事务,不调用 commit() 就不会真正写入数据库。
# 错误做法(会触发 N+1 次查询)
users = session.query(User).all()
for user in users:
print(user.name, user.orders) # 每次访问 orders 都会触发一次新查询
# 正确做法(使用 eager loading 一次性加载)
from sqlalchemy.orm import selectinload
users = session.query(User).options(selectinload(User.orders)).all()
for user in users:
print(user.name, user.orders) # 不再触发额外查询
原因:懒加载会导致循环中频繁查询数据库,性能极差。
# 错误做法
with Session(engine) as session1:
user = session1.query(User).first()
with Session(engine) as session2:
# user 属于 session1,不能在 session2 中使用
user.name = '新名字' # 可能报错或无法保存
session2.commit()
# 正确做法
with Session(engine) as session1:
user = session1.query(User).first()
user_id = user.id
with Session(engine) as session2:
user = session2.query(User).get(user_id)
user.name = '新名字'
session2.commit()
原因:每个 Session 维护自己的对象缓存,对象不能跨 Session 使用。
使用上下文管理器
# 推荐
with Session(engine) as session:
# 操作
pass
# 自动关闭 session
合理设置连接池大小
# 根据应用并发量调整
engine = create_engine('postgresql://...', pool_size=10, max_overflow=20)
使用环境变量存储敏感信息
import os
DATABASE_URL = os.getenv('DATABASE_URL', 'sqlite:///default.db')
engine = create_engine(DATABASE_URL)
添加索引优化查询
class User(Base):
email = Column(String(100), unique=True, index=True) # 为常用查询字段添加索引
使用类型提示提高代码质量(SQLAlchemy 2.0+)
from typing import Optional
from sqlalchemy.orm import Mapped, mapped_column
class User(Base):
name: Mapped[str] = mapped_column(String(50))
age: Mapped[Optional[int]] = mapped_column() # 可空字段
asyncio,可使用 AsyncSession 进行异步数据库操作bulk_insert_mappings 等方法进行高性能批量插入SQLAlchemy 是一个功能强大且设计优雅的 Python 数据库工具包。掌握它不仅能提升开发效率,还能帮助你更好地理解数据库和对象关系映射的原理。建议读者结合实际项目多加练习,逐步深入理解其高级特性。祝学习愉快!