Agent 开发者如何快速上手 SQL:从表设计到 Python 交互的一篇实战入门

目录

[一、先搞明白: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. 原生驱动)

PostgreSQL

MySQL

SQLite

[2. ORM 框架](#2. ORM 框架)

[常见 ORM:](#常见 ORM:)

[3. 数据库迁移工具](#3. 数据库迁移工具)

九、如何使用数据库:一个最实用的工作流

第一步:设计实体

第二步:设计表结构

第三步:建库建表

第四步:增删改查(CRUD)

第五步:事务控制

第六步:优化查询

[十、如何使用 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 应用,通常会涉及这些数据:

  1. 用户表

  2. 会话表

  3. 消息表

  4. 任务表

  5. 工具调用日志表

  6. 知识库文档表

  7. 检索结果缓存表

  8. 记忆表

举个简单例子:

用户发来一句话:

"帮我查一下上周销售异常的原因,并生成总结报告。"

这个过程里可能会产生:

  • 用户记录

  • 会话记录

  • 用户消息

  • Agent 回复

  • 任务执行状态

  • 调用数据库查询工具的日志

  • 报告生成结果

  • 长期记忆摘要

这些东西如果只靠内存放着,程序一重启就没了,像一只失忆的电子仓鼠。

所以数据库的作用,本质上就是:

让 Agent 拥有可追踪、可恢复、可分析、可扩展的状态能力。


三、关系型数据库最核心的几个概念

1. 数据库(Database)

数据库就是一整个数据集合。

比如你有一个项目叫 agent_app,它里面可能有很多表:

  • users

  • conversations

  • messages

  • tasks

  • tool_logs


2. 表(Table)

表就是数据的组织单位,像 Excel 表一样,但比 Excel 严肃得多。

例如 users 表:

id username email created_at

每一行是一条用户数据。


3. 字段 / 列(Column)

表里的每一列是一个字段,比如:

  • id

  • username

  • email

  • created_at

每个字段有自己的数据类型。


4. 行 / 记录(Row / Record)

每一行就是一条具体的数据。

比如:


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

一个用户对应一个详细资料。

示意:

这种关系不算最多,但有时为了拆分数据会用。


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 也是一对多。


它们之间的调用逻辑是怎样的?

假设用户发送:

"帮我总结最近三天的订单异常原因"

应用运行时可能是这样:

  1. users 中找到用户

  2. conversations 中创建一个新会话

  3. messages 中插入用户消息

  4. Agent 判断需要执行"订单分析任务"

  5. tasks 中创建一条任务记录,状态为 pending

  6. 调用某个分析工具

  7. tool_logs 中记录本次工具调用

  8. 工具执行完成后,更新 tasks.status = completed

  9. messages 中插入 Agent 回复

  10. 后续用户再追问时,系统可以根据 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)是数据库的一个重要能力。

它保证一组操作要么全部成功,要么全部失败。

比如:

  1. 创建任务

  2. 写工具调用日志

  3. 更新任务状态

如果第 2 步失败了,不应该让第 1 步已经写进去,第 3 步又没写。

否则数据会乱掉。

这就是事务存在的意义。


第六步:优化查询

当数据变多后,需要考虑:

  • 建索引

  • 减少无效 JOIN

  • 避免 SELECT *

  • 做分页

  • 做归档


十、如何使用 Python 与数据库交互

这部分最关键,我给你两个层次:

  1. 先用原生 sqlite3 看懂本质

  2. 再用 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 层

定义表结构和对象模型。

例如 UserConversationMessage


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,但你至少要具备下面这些能力:

  1. 能看懂和写基本 SQL

  2. 能设计基本表结构

  3. 能理解表之间的关系

  4. 能用 Python 完成数据库 CRUD

  5. 能在项目里使用 ORM

  6. 能理解事务、索引、迁移这些工程概念

你不需要一开始就把数据库玩成宗教。

但如果你完全不会,Agent 项目做到后面会很容易变成"数据乱飞、状态失踪、排障靠猜"的玄学现场。


十九、给你的建议:现在立刻怎么练

最适合你的起步方式不是继续看概念,而是直接做这三个练习:

练习 1: 用 SQLite 建 3 张表
usersconversationsmessages

练习 2: 用 Python 完成:

  • 创建用户

  • 创建会话

  • 插入消息

  • 查询某个会话的所有消息

练习 3: 用 SQLAlchemy 重写一遍

这一套走完,你对 SQL 的理解就不是"知道一点",而是已经能放进 Agent 项目里用了。

相关推荐
小张的博客之旅2 小时前
2026第十届“楚慧杯”湖北省网络与数据安全实践能力竞赛 (全Writeup)
python·网络安全·openclaw
new code Boy2 小时前
JavaScript转Python”的速查表
开发语言·javascript·python
杰杰7982 小时前
深入理解 Django REST Framework 的 Serializer(上)
后端·python·django
程序员敲代码吗2 小时前
探索数字转换与计算机存储基础
前端·python
深蓝电商API2 小时前
汽车之家车型参数对比表爬取
爬虫·python
codeJinger2 小时前
【Python】集合
开发语言·python
威联通安全存储2 小时前
严谨性的数字基石:某精密医疗器械企业基于威联通的数据治理实践
运维·数据库·python
计算机徐师兄2 小时前
Python基于Django的汉语文本阅读难度分级系统(附源码,文档说明)
python·机器学习·django·汉语文本阅读难度分级系统·python文本阅读难度分级·文本阅读难度分级系统·汉语文本阅读难度分级
LinuxGeek10242 小时前
从Centos-7迁移和升级到(银河麒麟)Kylin V7的教程
python·centos·kylin