数据库 / 已完成

关系型数据库和 SQL 够用基础

先补表、行、列、主键、外键、SQL、索引、事务和 ORM 对应关系。

返回文章积累

一句话:关系型数据库像一组有规则的表格,SQL 是你向这些表格查询、写入、修改和删除数据时使用的标准语言。

本篇学完你会什么:能看懂表、行、列、主键、外键、索引、事务这些词,知道 SQLAlchemy 背后其实是在帮你生成和执行 SQL。

1. 为什么学 ORM 前要先懂一点 SQL

FastAPI 项目里常用 SQLAlchemy 操作数据库。它很好用,但它不是“魔法数据库”,它只是帮你用 Python 写出数据库能听懂的 SQL。

如果完全不懂 SQL,看到这些代码会很晕:

stmt = select(User).where(User.username == "tom")
result = await db.execute(stmt)

其实它大概对应:

SELECT * FROM users WHERE username = 'tom';

所以这篇不追求把 SQL 学深,而是先补够后端开发最常用的那一层。

2. 表、行、列是什么

关系型数据库最基本的单位是表。

比如用户表 users

idusernameemailis_active
1tomtom@example.comtrue
2lucylucy@example.comtrue

大白话:

名词像什么例子
表 tableExcel 的一个工作表users
行 row一条数据id 为 1 的用户
列 column一个字段username
字段类型这一列能放什么intvarcharbool

后端接口里返回的 JSON,很多时候就是从数据库的一行或多行整理出来的。

3. 主键和唯一约束

主键是每一行数据的身份证。

CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  username VARCHAR(32) NOT NULL
);

id 是主键,意思是:

  • 每个用户都有自己的 id
  • id 不能重复
  • 查询、修改、删除时经常靠它定位数据

唯一约束是“这个字段也不能重复”。

CREATE UNIQUE INDEX ix_users_username ON users(username);

比如用户名不能重复、邮箱不能重复,就会用唯一约束。

4. 外键和表关系

真实业务通常不止一张表。

比如文章表 articles

idtitleauthor_id
10FastAPI 入门1

这里的 author_id = 1 指向 users.id = 1

大白话:文章表不需要把作者所有信息复制一遍,只要记住“作者是谁的 id”。

常见关系:

关系大白话例子
一对多一个用户有多篇文章users -> articles
多对一多篇文章属于一个用户articles -> users
多对多用户和角色互相关联users <-> roles

初学阶段先吃透一对多就够了。

5. 最常用的 SQL

查询

SELECT id, username FROM users WHERE id = 1;

意思:从 users 表里查 id 为 1 的用户,只拿 idusername

新增

INSERT INTO users (username, email)
VALUES ('tom', 'tom@example.com');

意思:新增一行用户数据。

修改

UPDATE users
SET email = 'new@example.com'
WHERE id = 1;

重点:修改和删除一定要带清楚 WHERE,否则可能影响很多行。

删除

DELETE FROM users WHERE id = 1;

练习时可以直接删,正式业务里经常用“软删除”,也就是加一个 deleted_atis_deleted 字段,而不是马上物理删除。

分页和排序

SELECT id, username
FROM users
ORDER BY id DESC
LIMIT 20 OFFSET 0;

对应接口里常见的:

GET /users?page=1&page_size=20

6. 索引是什么

索引像书的目录。

没有索引时,数据库可能要一行一行找:

SELECT * FROM users WHERE username = 'tom';

如果 username 上有索引,数据库能更快定位。

但索引不是越多越好:

  • 查询会更快
  • 写入可能变慢一点
  • 索引也占空间

初学阶段记住:经常用来查询、排序、关联的字段,才值得考虑索引。

7. 事务是什么

事务就是“几步操作要么一起成功,要么一起失败”。

比如下单:

扣库存
创建订单
记录支付流水

如果库存扣了,但订单创建失败,就会很麻烦。

事务保证:

全部成功 -> 提交 commit
中间失败 -> 回滚 rollback

在 SQLAlchemy 里,你会经常看到:

try:
    db.add(user)
    await db.commit()
except Exception:
    await db.rollback()
    raise

这就是在保护数据库状态。

8. SQL 和 ORM 怎么对应

SQL 概念SQLAlchemy 里常见写法大白话
class User(Base)用 Python 类描述表
mapped_column(...)用类属性描述字段
查询select(User)生成 SELECT
条件.where(User.id == 1)生成 WHERE
新增db.add(user)生成 INSERT
提交await db.commit()保存变更
回滚await db.rollback()撤销本次失败操作

你可以先把 ORM 当成“Python 风格的 SQL 生成器”。等项目复杂后,再深入学习关系加载、性能优化和事务边界。

9. 常见错误

问题原因解决
不知道该建几张表把所有字段塞一张表先按业务对象拆表,比如用户、文章、订单
修改数据影响太多行UPDATE 忘了 WHERE修改和删除前先确认条件
用户名重复报错唯一约束生效捕获冲突并返回 409
查询变慢没索引或一次查太多加合适索引,接口分页
数据只成功一半没理解事务关键流程用 commit/rollback
把 ORM 当黑盒不知道背后 SQL学会看日志里的 SQL

10. 学习顺序

建议按这个顺序来:

  1. 先会画出业务表:用户表、文章表、订单表。
  2. 再会写最常用 SQL:SELECTINSERTUPDATEDELETE
  3. 再理解主键、唯一约束、外键。
  4. 再理解索引和事务。
  5. 最后进入 SQLAlchemy CRUD。

总结表

名词大白话
数据库保存长期数据的资料室
同一类数据的表格
一条具体数据
数据的一个字段
主键每行数据的身份证
外键一张表指向另一张表的关联字段
SQL操作数据库的标准语言
索引帮数据库快速查找的目录
事务几步数据库操作要么全成,要么全撤
ORM用代码对象操作数据库的工具

下一篇建议:大白话讲解——FastAPI 连接数据库并实现增删改查