跳转到内容

3.5.2 关系型数据库基础

关系型数据库基础图

  • 理解什么是数据库以及为什么需要它
  • 掌握关系型数据库的核心概念
  • 理解表、行、列、主键、外键的含义
  • 了解常见的数据库管理系统

为什么 AI 工程师需要学数据库?

Section titled “为什么 AI 工程师需要学数据库?”

你可能会想:“我已经会用 Pandas 读 CSV 了,为什么还要学数据库?“

flowchart LR
A["CSV / Excel 文件"] --> B{"数据量"}
B -->|"几万行"| C["Pandas 足够"]
B -->|"几百万行"| D["需要数据库"]
B -->|"多人同时用"| D
B -->|"需要安全存储"| D
style C fill:#e8f5e9,stroke:#2e7d32,color:#333
style D fill:#fff3e0,stroke:#e65100,color:#333
场景CSV 文件数据库
数据量几万行还行,百万行卡死轻松处理上亿行
多人协作谁改了不知道,容易冲突支持并发读写,有权限控制
数据安全文件删了就没了有备份、事务、崩溃恢复
查询速度每次都要全量扫描有索引,毫秒级查询
数据关联手动 merge 多个文件用 SQL JOIN 一句搞定

真实场景举例:

  • 做 RAG 系统 → 用户问答记录要存数据库
  • 做 AI Agent → 记忆系统需要持久化存储
  • 做推荐系统 → 用户行为数据在数据库里
  • 做数据分析 → 企业数据 99% 存在数据库中

如果你用过 Excel,你已经理解了关系型数据库 80% 的概念:

Excel 概念数据库概念说明
一个 Excel 文件一个数据库(Database)存放所有数据的容器
一个 Sheet 工作表一张(Table)存放某一类数据
一行一条记录(Row / Record)一个具体的数据实体
一列一个字段(Column / Field)数据的一个属性
列标题字段名(Column Name)属性名称
单元格的数据类型数据类型(Data Type)整数、文本、日期等

假设你开了一家网店,需要管理用户订单

用户表(users):

订单表(orders):

  • order_id=101user_id=1,iPhone 16,7999,2024-11-01
  • order_id=102user_id=1,AirPods,999,2024-11-05
  • order_id=103user_id=2,MacBook,14999,2024-11-10

这两张表通过 user_id 关联——这就是关系型数据库名字的由来:表与表之间存在关系


主键是每条记录的唯一标识,就像身份证号一样,不能重复、不能为空。

用户表中:id 是主键 → 每个用户有唯一的 id
订单表中:order_id 是主键 → 每个订单有唯一的 order_id

外键是指引用另一张表主键的字段,用于建立表之间的关系。

flowchart LR
subgraph users["用户表 users"]
U["id (主键) | name | email"]
end
subgraph orders["订单表 orders"]
O["order_id (主键) | user_id (外键) | product"]
end
orders -->|"user_id 引用"| users
style users fill:#e3f2fd,stroke:#1565c0,color:#333
style orders fill:#fff3e0,stroke:#e65100,color:#333

订单表中的 user_id 就是外键——它指向用户表的 id,表示”这个订单属于哪个用户”。

类型说明示例
INTEGER整数1, 42, -100
REAL / FLOAT浮点数3.14, 99.9
TEXT / VARCHAR文本字符串”张三”, “hello”
DATE日期2024-11-01
DATETIME日期时间2024-11-01 14:30:00
BOOLEAN布尔值TRUE / FALSE
BLOB二进制数据图片、文件(不常用)

约束是对数据的规则限制,保证数据质量:

约束作用示例
PRIMARY KEY主键,唯一且不为空id
NOT NULL不能为空name NOT NULL
UNIQUE值不能重复email UNIQUE
DEFAULT默认值city DEFAULT '未知'
FOREIGN KEY外键,引用其他表user_id REFERENCES users(id)

学完这一页,至少保留这张证据卡:

架构
表名、键、关系和示例行
查询
所使用的 SQL 或 Python 数据库代码
输出
结果行、行数,或保存的抽取结果
失败检查
错误的连接键、不安全查询、缺少事务,或 schema 不匹配
期望产出
查询、结果表和一条数据质量说明
数据库特点适用场景
SQLite零配置,存在单个文件中学习、小应用、移动端
MySQL最流行的开源数据库Web 应用、中小型项目
PostgreSQL功能最强大的开源数据库大型项目、AI 应用(支持向量搜索)
SQL Server微软出品企业级 Windows 环境

第一次学数据库时,最稳的默认顺序

Section titled “第一次学数据库时,最稳的默认顺序”

更稳的顺序通常是:

  1. 先把“表、主键、外键”看顺
  2. 再学 SQL 查询
  3. 再让 Python 连数据库
  4. 最后再看数据库设计

这样会比一开始就背很多 SQL 细节更不容易乱。


import sqlite3
# 1. 连接数据库(不存在则自动创建)
conn = sqlite3.connect("my_shop.db")
cursor = conn.cursor()
# 2. 创建用户表
cursor.execute("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE,
age INTEGER,
city TEXT DEFAULT '未知'
)
""")
# 3. 插入数据
cursor.execute("INSERT INTO users (name, email, age, city) VALUES ('张三', '[email protected]', 28, '北京')")
cursor.execute("INSERT INTO users (name, email, age, city) VALUES ('李四', '[email protected]', 35, '上海')")
cursor.execute("INSERT INTO users (name, email, age, city) VALUES ('王五', '[email protected]', 22, '广州')")
# 4. 提交更改
conn.commit()
# 5. 查询数据
cursor.execute("SELECT * FROM users")
rows = cursor.fetchall()
for row in rows:
print(row)
# (1, '张三', '[email protected]', 28, '北京')
# (2, '李四', '[email protected]', 35, '上海')
# (3, '王五', '[email protected]', 22, '广州')
# 6. 关闭连接
conn.close()

恭喜!你刚刚创建了一个数据库、一张表,并存入了 3 条数据。

这个小示例最值得先学到什么?

Section titled “这个小示例最值得先学到什么?”

最值得先学到的不是每个 SQL 关键字, 而是数据库最小工作流其实很朴素:

  1. 连上数据库
  2. 创建表
  3. 插入数据
  4. 查询结果

只要这条线先顺了,后面学 SQL 和 Python 连接就不会那么虚。


root(("关系型数据库"))
核心概念
数据库 Database
表 Table
行 Row
列 Column
关键机制
主键 PK
外键 FK
约束 Constraints
数据类型
常用数据库
SQLite(学习用)
MySQL
PostgreSQL
SQL Server
概念一句话理解
数据库存放所有表的”文件夹”
一类数据的”Excel 工作表”
主键每条记录的”身份证号”
外键连接两张表的”纽带”
约束保证数据质量的”规则”
  • 关系型数据库最重要的不是“存很多表”,而是表和表之间能通过键建立关系
  • 主键负责唯一标识,外键负责把表接起来
  • 这一节先立住了,后面的 SQL 和多表分析才会顺

为一个图书管理系统设计两张表:
- books 表:书名、作者、出版年份、价格、分类
- borrows 表:借阅记录(谁借了哪本书、借阅日期、归还日期)
思考:
1. 每张表的主键是什么?
2. borrows 表需要哪些外键?
3. 哪些字段应该加 NOT NULL 约束?
# 使用 sqlite3 创建上面设计的 books 表和 borrows 表
# 插入 5 本书和 3 条借阅记录
# 查询所有数据并打印
参考实现与讲解
  • 简单图书馆数据库通常需要 books 表,以 book_id 作为主键,还需要借阅表,包含自己的 borrow_id 以及指向图书和借阅人的外键。
  • 书名、作者、借阅人、借阅日期这类必填字段用 NOT NULL。归还日期等字段可以允许为空,因为借出时还不知道。
  • 建表后插入两三行数据并运行一次 join 查询。只有能回答真实问题,schema 设计才有说服力。