目录
[一、先搞明白:SQL 到底是什么](#一、先搞明白:SQL 到底是什么)
[二、为什么 Agent 项目离不开数据库](#二、为什么 Agent 项目离不开数据库)
[1. 数据库(Database)](#1. 数据库(Database))
[2. 表(Table)](#2. 表(Table))
[3. 字段 / 列(Column)](#3. 字段 / 列(Column))
[4. 行 / 记录(Row / Record)](#4. 行 / 记录(Row / Record))
[5. 主键(Primary Key)](#5. 主键(Primary Key))
[6. 外键(Foreign Key)](#6. 外键(Foreign Key))
[1. 一对一(One-to-One)](#1. 一对一(One-to-One))
[2. 一对多(One-to-Many)](#2. 一对多(One-to-Many))
[3. 多对多(Many-to-Many)](#3. 多对多(Many-to-Many))
[五、用一个 Agent 项目例子理解表之间的关系](#五、用一个 Agent 项目例子理解表之间的关系)
[1. users(用户表)](#1. users(用户表))
[2. conversations(会话表)](#2. conversations(会话表))
[3. messages(消息表)](#3. messages(消息表))
[4. tasks(任务表)](#4. tasks(任务表))
[5. tool_logs(工具调用日志表)](#5. tool_logs(工具调用日志表))
[六、SQL 最常用的基本语句](#六、SQL 最常用的基本语句)
[1. CREATE:创建表](#1. CREATE:创建表)
[2. INSERT:插入数据](#2. INSERT:插入数据)
[3. SELECT:查询数据](#3. SELECT:查询数据)
[4. UPDATE:更新数据](#4. UPDATE:更新数据)
[5. DELETE:删除数据](#5. DELETE:删除数据)
[6. ORDER BY:排序](#6. ORDER BY:排序)
[7. LIMIT:限制返回数量](#7. LIMIT:限制返回数量)
[8. JOIN:关联查询](#8. JOIN:关联查询)
[七、你必须知道的几个 SQL 设计原则](#七、你必须知道的几个 SQL 设计原则)
[1. 不要把所有东西塞进一张表](#1. 不要把所有东西塞进一张表)
[2. 每张表只描述一种核心实体](#2. 每张表只描述一种核心实体)
[3. 用主键和外键建立关系](#3. 用主键和外键建立关系)
[4. 高频查询字段要考虑加索引](#4. 高频查询字段要考虑加索引)
[5. 状态类字段尽量统一](#5. 状态类字段尽量统一)
[1. 原生驱动](#1. 原生驱动)
[2. ORM 框架](#2. ORM 框架)
[常见 ORM:](#常见 ORM:)
[3. 数据库迁移工具](#3. 数据库迁移工具)
[十、如何使用 Python 与数据库交互](#十、如何使用 Python 与数据库交互)
[十一、方式一:使用 sqlite3 进行最基础交互](#十一、方式一:使用 sqlite3 进行最基础交互)
[1. 创建数据库和表](#1. 创建数据库和表)
[2. 插入数据](#2. 插入数据)
[3. 查询数据](#3. 查询数据)
[4. 更新数据](#4. 更新数据)
[5. 删除数据](#5. 删除数据)
[十二、方式二:使用 SQLAlchemy 进行项目级开发](#十二、方式二:使用 SQLAlchemy 进行项目级开发)
[1. 定义模型](#1. 定义模型)
[2. 创建数据库连接和表](#2. 创建数据库连接和表)
[3. 插入数据](#3. 插入数据)
[4. 查询数据](#4. 查询数据)
[5. 插入关联数据](#5. 插入关联数据)
[6. 查询关联关系](#6. 查询关联关系)
[十三、在 Agent 项目中,数据库一般怎么和 Python 应用对接](#十三、在 Agent 项目中,数据库一般怎么和 Python 应用对接)
[1. Model 层](#1. Model 层)
[2. Repository / DAO 层](#2. Repository / DAO 层)
[3. Service 层](#3. Service 层)
[4. API / Agent Workflow 层](#4. API / Agent Workflow 层)
[十四、一个适合 Agent 项目的数据库实战建议](#十四、一个适合 Agent 项目的数据库实战建议)
[Memory 相关表](#Memory 相关表)
[十五、初学 SQL 最容易踩的坑](#十五、初学 SQL 最容易踩的坑)
[1. 把数据库当成 JSON 垃圾桶](#1. 把数据库当成 JSON 垃圾桶)
[2. 不设计外键关系](#2. 不设计外键关系)
[3. 不会 JOIN](#3. 不会 JOIN)
[4. 不懂事务](#4. 不懂事务)
[5. 所有查询都 SELECT *](#5. 所有查询都 SELECT *)
[第一阶段:理解 SQL 基础](#第一阶段:理解 SQL 基础)
[第三阶段:用 SQLite 写一个小项目](#第三阶段:用 SQLite 写一个小项目)
[第四阶段:切到 PostgreSQL + SQLAlchemy](#第四阶段:切到 PostgreSQL + SQLAlchemy)
[第五阶段:学迁移工具 Alembic](#第五阶段:学迁移工具 Alembic)
[十七、一个最小可运行的 Python + SQLAlchemy 示例](#十七、一个最小可运行的 Python + SQLAlchemy 示例)
很多做 Agent 的开发者,一开始会把注意力放在模型、Prompt、Tool Calling、Memory、RAG 上。结果项目一旦开始落地,很快就会撞上一个朴素但凶猛的问题:
数据到底怎么存?
比如:
-
用户信息怎么存
-
会话历史怎么存
-
Agent 任务怎么存
-
工具调用日志怎么存
-
文档索引和知识库元数据怎么存
-
哪些数据该长期保存,哪些数据该临时缓存
这时候,SQL 和数据库就不是"后端工程师的事"了,而是你这个 Agent 开发者必须掌握的基础能力。
这篇文章会带你快速建立一套能直接用于项目的认知框架。
一、先搞明白:SQL 到底是什么
SQL,全称 Structured Query Language ,结构化查询语言。
它不是某一个数据库产品,而是一套和关系型数据库沟通的语言。
你可以把它理解成:
-
数据库:仓库
-
表(table):仓库里的分类货架
-
SQL:你和仓库管理员说话的方式
你说:
-
给我创建一个用户表
-
插入一个新用户
-
查出最近 7 天的会话
-
更新某个任务状态
-
删除过期日志
这些本质上都是 SQL 在干活。
常见的关系型数据库有:
-
PostgreSQL:功能强,适合正式项目,Agent 系统里很常见
-
MySQL:流行度高,很多 Web 项目在用
-
SQLite:轻量,单文件,适合本地开发和小项目
-
MariaDB:MySQL 的分支
对于 Agent 项目,我很建议你优先熟悉:
-
本地练手:SQLite
-
真正做应用:PostgreSQL
原因很现实:PostgreSQL 对 JSON、事务、索引、扩展能力支持都很强,很适合 Agent 系统这种"结构化数据 + 半结构化数据混合"的场景。
二、为什么 Agent 项目离不开数据库
一个稍微完整一点的 Agent 应用,通常会涉及这些数据:
-
用户表
-
会话表
-
消息表
-
任务表
-
工具调用日志表
-
知识库文档表
-
检索结果缓存表
-
记忆表
举个简单例子:
用户发来一句话:
"帮我查一下上周销售异常的原因,并生成总结报告。"
这个过程里可能会产生:
-
用户记录
-
会话记录
-
用户消息
-
Agent 回复
-
任务执行状态
-
调用数据库查询工具的日志
-
报告生成结果
-
长期记忆摘要
这些东西如果只靠内存放着,程序一重启就没了,像一只失忆的电子仓鼠。
所以数据库的作用,本质上就是:
让 Agent 拥有可追踪、可恢复、可分析、可扩展的状态能力。
三、关系型数据库最核心的几个概念
1. 数据库(Database)
数据库就是一整个数据集合。
比如你有一个项目叫 agent_app,它里面可能有很多表:
-
users
-
conversations
-
messages
-
tasks
-
tool_logs
2. 表(Table)
表就是数据的组织单位,像 Excel 表一样,但比 Excel 严肃得多。
例如 users 表:
| id | username | created_at |
|---|
每一行是一条用户数据。
3. 字段 / 列(Column)
表里的每一列是一个字段,比如:
-
id
-
username
-
email
-
created_at
每个字段有自己的数据类型。
4. 行 / 记录(Row / Record)
每一行就是一条具体的数据。
比如:
-
id = 1
-
username = "zhangsan"
-
email = "zhangsan@example.com"
5. 主键(Primary Key)
主键是每条记录的唯一标识。
通常会用:
sql
id INT PRIMARY KEY
或者更常见:
sql
id SERIAL PRIMARY KEY
意思是:这个字段唯一,而且不能重复。
你可以把主键理解成每条数据的身份证号。
6. 外键(Foreign Key)
外键用于建立表和表之间的联系。
比如 messages 表里的 conversation_id,指向 conversations 表的 id。
这就表示:
这条消息属于哪个会话。
四、数据库中表与表之间的关系
这部分非常关键。
你以后设计 Agent 数据结构,90% 的混乱都出在这里。
1. 一对一(One-to-One)
一张表中的一条记录,只对应另一张表中的一条记录。
比如:
-
users表 -
user_profiles表
一个用户对应一个详细资料。
示意:
-
user.id = 1
-
profile.user_id = 1
这种关系不算最多,但有时为了拆分数据会用。
2. 一对多(One-to-Many)
这是最常见的关系。
比如:
-
一个用户可以有多个会话
-
一个会话可以有多条消息
-
一个任务可以有多个执行日志
示意:
-
users.id = 1
-
conversations.user_id = 1, 1, 1
说明一个用户对应多个会话。
3. 多对多(Many-to-Many)
比如:
-
一个文档可以有多个标签
-
一个标签也可以属于多个文档
这时候一般要引入一张中间表。
例如:
-
documents
-
tags
-
document_tags
document_tags 里存:
-
document_id
-
tag_id
这就是多对多关系的标准做法。
五、用一个 Agent 项目例子理解表之间的关系
假设你在做一个 Agent 应用,支持:
-
用户对话
-
历史会话保存
-
工具调用记录
-
任务执行追踪
那你可能会设计这样的表:
1. users(用户表)
sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
2. conversations(会话表)
sql
CREATE TABLE conversations (
id SERIAL PRIMARY KEY,
user_id INT NOT NULL,
title VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
一个用户可以有多个会话,所以这是users -> conversations 的一对多。
3. messages(消息表)
sql
CREATE TABLE messages (
id SERIAL PRIMARY KEY,
conversation_id INT NOT NULL,
role VARCHAR(50) NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (conversation_id) REFERENCES conversations(id)
);
一个会话可以有多条消息,所以这是conversations -> messages 的一对多。
role 一般存:
-
user
-
assistant
-
system
-
tool
4. tasks(任务表)
sql
CREATE TABLE tasks (
id SERIAL PRIMARY KEY,
conversation_id INT NOT NULL,
task_type VARCHAR(100) NOT NULL,
status VARCHAR(50) NOT NULL,
result TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (conversation_id) REFERENCES conversations(id)
);
一个会话里可能触发多个任务,所以也是一对多。
5. tool_logs(工具调用日志表)
sql
CREATE TABLE tool_logs (
id SERIAL PRIMARY KEY,
task_id INT NOT NULL,
tool_name VARCHAR(100) NOT NULL,
input_data TEXT,
output_data TEXT,
status VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (task_id) REFERENCES tasks(id)
);
一个任务可能调用多个工具,所以 tasks -> tool_logs 也是一对多。
它们之间的调用逻辑是怎样的?
假设用户发送:
"帮我总结最近三天的订单异常原因"
应用运行时可能是这样:
-
在
users中找到用户 -
在
conversations中创建一个新会话 -
在
messages中插入用户消息 -
Agent 判断需要执行"订单分析任务"
-
在
tasks中创建一条任务记录,状态为pending -
调用某个分析工具
-
在
tool_logs中记录本次工具调用 -
工具执行完成后,更新
tasks.status = completed -
在
messages中插入 Agent 回复 -
后续用户再追问时,系统可以根据
conversation_id找到完整上下文
这就是数据库在 Agent 项目里的价值:
它不是单纯存数据,而是在支撑系统状态流转。
六、SQL 最常用的基本语句
这部分你一定要会,因为 ORM 再高级,底层还是这些逻辑。
1. CREATE:创建表
sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE
);
2. INSERT:插入数据
sql
INSERT INTO users (username, email)
VALUES ('alice', 'alice@example.com');
3. SELECT:查询数据
查询所有用户:
sql
SELECT * FROM users;
查询指定字段:
sql
SELECT id, username FROM users;
带条件查询:
sql
SELECT * FROM users
WHERE username = 'alice';
4. UPDATE:更新数据
sql
UPDATE users
SET email = 'newalice@example.com'
WHERE id = 1;
5. DELETE:删除数据
sql
DELETE FROM users
WHERE id = 1;
6. ORDER BY:排序
sql
SELECT * FROM messages
ORDER BY created_at DESC;
7. LIMIT:限制返回数量
sql
SELECT * FROM messages
ORDER BY created_at DESC
LIMIT 10;
8. JOIN:关联查询
这是 SQL 的精髓之一。
比如查某个用户的所有会话:
sql
SELECT conversations.id, conversations.title, users.username
FROM conversations
JOIN users ON conversations.user_id = users.id
WHERE users.id = 1;
再比如查某个会话下的所有消息:
sql
SELECT messages.id, messages.role, messages.content, conversations.title
FROM messages
JOIN conversations ON messages.conversation_id = conversations.id
WHERE conversations.id = 100;
JOIN 的本质就是:
把多张表按关系拼起来查。
七、你必须知道的几个 SQL 设计原则
1. 不要把所有东西塞进一张表
新手特别容易犯这个毛病。
比如把用户、会话、消息、任务全塞一个大表里。那后面查询和维护会烂成一锅电子粥。
应该按职责拆表。
2. 每张表只描述一种核心实体
例如:
-
users:描述用户
-
conversations:描述会话
-
messages:描述消息
-
tasks:描述任务
一张表一个主题,清晰很多。
3. 用主键和外键建立关系
不要靠字符串乱连,比如:
-
username = 'alice' -
conversation_name = 'chat_001'
这些都不稳定。
稳定关系应靠 id。
4. 高频查询字段要考虑加索引
比如:
-
user_id
-
conversation_id
-
created_at
-
status
如果后面数据量大,不加索引,查询会越来越慢,像背着冰箱跑步。
例如:
sql
CREATE INDEX idx_messages_conversation_id ON messages(conversation_id);
5. 状态类字段尽量统一
例如任务状态统一用:
-
pending
-
running
-
completed
-
failed
不要今天写 done,明天写 finish,后天写 successfully_finished_final_version_v2。
这不是灵活,这是灾难艺术。
八、常用数据库框架和工具
你问的是"常用框架",那我直接按 Python 开发视角给你分层。
1. 原生驱动
它们负责 Python 和数据库直接通信。
PostgreSQL
-
psycopg2 -
psycopg(新版本,更推荐)
MySQL
-
pymysql -
mysqlclient
SQLite
- Python 内置
sqlite3
适合场景:
-
想理解底层
-
写简单脚本
-
对 SQL 控制要求很高
2. ORM 框架
ORM,全称 Object-Relational Mapping ,对象关系映射。
它的作用是让你用 Python 类和对象来操作数据库,而不是全手写 SQL。
常见 ORM:
-
SQLAlchemy:Python 里最主流,功能强,工业级
-
SQLModel:基于 SQLAlchemy,语法更现代,和 Pydantic 很搭
-
Django ORM:如果你用 Django 做 Web,很方便
-
Peewee:轻量,适合中小项目
对于 Agent 项目,我最推荐:
-
入门理解底层:sqlite3 + SQL
-
正式开发:SQLAlchemy
-
想写得更丝滑一些:SQLModel
3. 数据库迁移工具
数据库结构不是一开始就完美的,后面会经常改表结构。
比如:
-
给 messages 表加一个 token_count 字段
-
给 tasks 表加一个 retry_count 字段
这时候就需要迁移工具。
常见的:
-
Alembic:SQLAlchemy 生态最常用
-
Django 自带 migration
你前面学到的:
python
python -m alembic upgrade head
本质上就是把数据库结构升级到最新版本。
九、如何使用数据库:一个最实用的工作流
数据库不是"装好了就完事"。你在项目里一般会经历下面这套流程:
第一步:设计实体
先想清楚你的系统里有哪些核心对象:
-
用户
-
会话
-
消息
-
工具调用
-
任务
-
文档
-
记忆
第二步:设计表结构
确定:
-
每张表有哪些字段
-
主键是什么
-
外键怎么关联
-
哪些字段不能为空
-
哪些字段唯一
-
哪些字段要索引
第三步:建库建表
用 SQL 或 ORM 创建表。
第四步:增删改查(CRUD)
CRUD 是四大基础操作:
-
Create:创建
-
Read:读取
-
Update:更新
-
Delete:删除
第五步:事务控制
事务(Transaction)是数据库的一个重要能力。
它保证一组操作要么全部成功,要么全部失败。
比如:
-
创建任务
-
写工具调用日志
-
更新任务状态
如果第 2 步失败了,不应该让第 1 步已经写进去,第 3 步又没写。
否则数据会乱掉。
这就是事务存在的意义。
第六步:优化查询
当数据变多后,需要考虑:
-
建索引
-
减少无效 JOIN
-
避免 SELECT *
-
做分页
-
做归档
十、如何使用 Python 与数据库交互
这部分最关键,我给你两个层次:
-
先用原生 sqlite3 看懂本质
-
再用 SQLAlchemy 进入正式项目写法
十一、方式一:使用 sqlite3 进行最基础交互
SQLite 非常适合入门,因为它不需要单独启动数据库服务。
1. 创建数据库和表
python
import sqlite3
conn = sqlite3.connect("agent_app.db")
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL,
email TEXT UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
conn.commit()
conn.close()
这里做了什么?
-
connect():连接数据库文件 -
cursor():创建操作游标 -
execute():执行 SQL -
commit():提交修改 -
close():关闭连接
2. 插入数据
python
import sqlite3
conn = sqlite3.connect("agent_app.db")
cursor = conn.cursor()
cursor.execute(
"INSERT INTO users (username, email) VALUES (?, ?)",
("alice", "alice@example.com")
)
conn.commit()
conn.close()
注意这里用了 ? 占位符。
这是为了防止 SQL 注入,不要自己拼接字符串。
错误写法:
python
username = "alice"
sql = f"SELECT * FROM users WHERE username = '{username}'"
这很危险。项目里别这么整,容易被人拿数据库当沙滩玩具。
3. 查询数据
python
import sqlite3
conn = sqlite3.connect("agent_app.db")
cursor = conn.cursor()
cursor.execute("SELECT id, username, email FROM users")
rows = cursor.fetchall()
for row in rows:
print(row)
conn.close()
4. 更新数据
python
import sqlite3
conn = sqlite3.connect("agent_app.db")
cursor = conn.cursor()
cursor.execute(
"UPDATE users SET email = ? WHERE username = ?",
("newalice@example.com", "alice")
)
conn.commit()
conn.close()
5. 删除数据
python
import sqlite3
conn = sqlite3.connect("agent_app.db")
cursor = conn.cursor()
cursor.execute("DELETE FROM users WHERE username = ?", ("alice",))
conn.commit()
conn.close()
十二、方式二:使用 SQLAlchemy 进行项目级开发
如果你要做正式项目,建议尽快上 SQLAlchemy。
因为它能让你:
-
管理模型
-
管理连接
-
管理事务
-
更好地和 FastAPI、Flask 等项目集成
先安装:
pip install sqlalchemy
如果是 PostgreSQL:
pip install sqlalchemy psycopg
1. 定义模型
python
from sqlalchemy import create_engine, Column, Integer, String, Text, ForeignKey, DateTime
from sqlalchemy.orm import declarative_base, relationship, sessionmaker
from datetime import datetime
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
username = Column(String(100), nullable=False)
email = Column(String(255), unique=True)
created_at = Column(DateTime, default=datetime.utcnow)
conversations = relationship("Conversation", back_populates="user")
class Conversation(Base):
__tablename__ = "conversations"
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
title = Column(String(255))
created_at = Column(DateTime, default=datetime.utcnow)
user = relationship("User", back_populates="conversations")
messages = relationship("Message", back_populates="conversation")
class Message(Base):
__tablename__ = "messages"
id = Column(Integer, primary_key=True)
conversation_id = Column(Integer, ForeignKey("conversations.id"), nullable=False)
role = Column(String(50), nullable=False)
content = Column(Text, nullable=False)
created_at = Column(DateTime, default=datetime.utcnow)
conversation = relationship("Conversation", back_populates="messages")
2. 创建数据库连接和表
SQLite 示例:
python
engine = create_engine("sqlite:///agent_app.db", echo=True)
Base.metadata.create_all(engine)
SessionLocal = sessionmaker(bind=engine)
PostgreSQL 示例:
python
engine = create_engine("postgresql+psycopg://postgres:password@localhost:5432/agent_app")
3. 插入数据
python
session = SessionLocal()
new_user = User(username="alice", email="alice@example.com")
session.add(new_user)
session.commit()
session.close()
4. 查询数据
python
session = SessionLocal()
users = session.query(User).all()
for user in users:
print(user.id, user.username, user.email)
session.close()
5. 插入关联数据
python
session = SessionLocal()
user = session.query(User).filter_by(username="alice").first()
conv = Conversation(user_id=user.id, title="订单异常分析")
session.add(conv)
session.commit()
msg = Message(conversation_id=conv.id, role="user", content="帮我分析最近三天订单异常")
session.add(msg)
session.commit()
session.close()
6. 查询关联关系
python
session = SessionLocal()
conv = session.query(Conversation).first()
print(conv.title)
for msg in conv.messages:
print(msg.role, msg.content)
session.close()
这就是 ORM 的舒服之处。
你操作的不再只是表,而是 Python 对象之间的关系。
十三、在 Agent 项目中,数据库一般怎么和 Python 应用对接
你可以把数据库交互理解成这样几层:
1. Model 层
定义表结构和对象模型。
例如 User、Conversation、Message。
2. Repository / DAO 层
专门封装数据库操作逻辑。
例如:
python
def create_user(session, username, email):
user = User(username=username, email=email)
session.add(user)
session.commit()
session.refresh(user)
return user
python
def get_conversation_messages(session, conversation_id):
return session.query(Message).filter_by(conversation_id=conversation_id).all()
这样做的好处是:
你的业务逻辑不会和 SQL/ORM 代码混在一起。
3. Service 层
负责业务编排。
例如:
-
创建会话
-
保存消息
-
创建任务
-
写工具日志
-
更新任务状态
4. API / Agent Workflow 层
用户请求进来后,调用 service 层处理。
这才是一个比较健康的结构。
十四、一个适合 Agent 项目的数据库实战建议
如果你在做 Agent 系统,我建议你至少准备这些表:
基础表
-
users -
conversations -
messages
任务与执行表
-
tasks -
tool_logs -
workflows
知识库相关表
-
documents -
document_chunks -
retrieval_logs
Memory 相关表
-
memories -
memory_links -
memory_updates
这样你后续想做:
-
长短期记忆
-
RAG 检索记录
-
工具执行追踪
-
可观测性分析
-
用户行为统计
都会很自然。
十五、初学 SQL 最容易踩的坑
1. 把数据库当成 JSON 垃圾桶
很多人一开始图省事,什么都往一个大 JSON 字段里塞。
这不是不能做,而是不能全都这么做。
适合结构化的数据,老老实实建表。
JSON 更适合:
-
tool input/output
-
动态配置
-
不固定扩展字段
2. 不设计外键关系
没有外键,后面数据关联会很痛苦。
你会发现表看起来都在,实际上全是"无亲无故的数据孤儿"。
3. 不会 JOIN
不会 JOIN,数据库只能当半个 Excel 用。
一旦要做真实业务查询,马上抓瞎。
4. 不懂事务
这会导致业务执行一半成功一半失败,状态乱掉。
尤其在任务系统、订单系统、Agent 工作流里很危险。
5. 所有查询都 SELECT *
这在小数据量下还能混,数据一大就会又慢又浪费资源。
该查什么字段,就查什么字段。
十六、给你的学习路线建议
如果你的目标是"快速上手并能写项目",建议这样学:
第一阶段:理解 SQL 基础
掌握:
-
CREATE TABLE
-
INSERT
-
SELECT
-
UPDATE
-
DELETE
-
WHERE
-
ORDER BY
-
LIMIT
-
JOIN
第二阶段:理解表关系
重点掌握:
-
主键
-
外键
-
一对一
-
一对多
-
多对多
第三阶段:用 SQLite 写一个小项目
比如做一个最小 Agent 数据存储系统:
-
用户表
-
会话表
-
消息表
先把增删改查打通。
第四阶段:切到 PostgreSQL + SQLAlchemy
因为这才更接近真实生产环境。
第五阶段:学迁移工具 Alembic
因为只会建表不够,后面你一定会改表。
十七、一个最小可运行的 Python + SQLAlchemy 示例
下面给你一个很适合练手的完整小例子:
python
from datetime import datetime
from sqlalchemy import create_engine, Column, Integer, String, Text, ForeignKey, DateTime
from sqlalchemy.orm import declarative_base, relationship, sessionmaker
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
username = Column(String(100), nullable=False)
email = Column(String(255), unique=True)
created_at = Column(DateTime, default=datetime.utcnow)
conversations = relationship("Conversation", back_populates="user")
class Conversation(Base):
__tablename__ = "conversations"
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
title = Column(String(255))
created_at = Column(DateTime, default=datetime.utcnow)
user = relationship("User", back_populates="conversations")
messages = relationship("Message", back_populates="conversation")
class Message(Base):
__tablename__ = "messages"
id = Column(Integer, primary_key=True)
conversation_id = Column(Integer, ForeignKey("conversations.id"), nullable=False)
role = Column(String(50), nullable=False)
content = Column(Text, nullable=False)
created_at = Column(DateTime, default=datetime.utcnow)
conversation = relationship("Conversation", back_populates="messages")
engine = create_engine("sqlite:///agent_demo.db", echo=False)
Base.metadata.create_all(engine)
SessionLocal = sessionmaker(bind=engine)
session = SessionLocal()
# 1. 创建用户
user = User(username="alice", email="alice@example.com")
session.add(user)
session.commit()
session.refresh(user)
# 2. 创建会话
conversation = Conversation(user_id=user.id, title="Agent SQL 学习")
session.add(conversation)
session.commit()
session.refresh(conversation)
# 3. 插入消息
msg1 = Message(conversation_id=conversation.id, role="user", content="什么是 SQL?")
msg2 = Message(conversation_id=conversation.id, role="assistant", content="SQL 是结构化查询语言。")
session.add_all([msg1, msg2])
session.commit()
# 4. 查询结果
conversations = session.query(Conversation).all()
for conv in conversations:
print(f"会话: {conv.title}")
for msg in conv.messages:
print(f" [{msg.role}] {msg.content}")
session.close()
这个例子虽然小,但很有代表性。
你已经能从这里延伸出:
-
会话系统
-
Chat 记录存储
-
Agent 执行链路存储
-
Memory 系统
十八、最后给你一个务实结论
如果你是 Agent 开发人员,SQL 不需要你上来就学成 DBA,但你至少要具备下面这些能力:
-
能看懂和写基本 SQL
-
能设计基本表结构
-
能理解表之间的关系
-
能用 Python 完成数据库 CRUD
-
能在项目里使用 ORM
-
能理解事务、索引、迁移这些工程概念
你不需要一开始就把数据库玩成宗教。
但如果你完全不会,Agent 项目做到后面会很容易变成"数据乱飞、状态失踪、排障靠猜"的玄学现场。
十九、给你的建议:现在立刻怎么练
最适合你的起步方式不是继续看概念,而是直接做这三个练习:
练习 1: 用 SQLite 建 3 张表
users、conversations、messages
练习 2: 用 Python 完成:
-
创建用户
-
创建会话
-
插入消息
-
查询某个会话的所有消息
练习 3: 用 SQLAlchemy 重写一遍
这一套走完,你对 SQL 的理解就不是"知道一点",而是已经能放进 Agent 项目里用了。