📚前言
📒FDE系列内容总纲:
🚄前置课程列表:
见文档结尾附录。
🚀阶段2·Day 31:SQL 基础 --- 增删改查一把梭
FDE 学习系列教程 · 第二阶段 · 第 3 周 · Day 1 预计时长:2.5 小时 | 难度:★★☆☆☆ | 前置知识:Python 基础、FastAPI CRUD
📌 一句话目标:搞懂数据库是啥,在 SQLite 里建表、插数据,写出 SELECT / WHERE / ORDER BY / LIMIT,把增删改查(CRUD)的骨架完整走一遍。
🧑🤝🧑 开场:你的数据终于有个正经"家"了
兄弟,前面两周你的工单数据全存在 Python 列表里:
TICKETS = [{"id": 1, "title": "温度偏高"}, {...}]
发现问题了吗?程序一关,数据全没了。 重启服务,列表清空,之前建的工单人间蒸发。这要是在客户现场,第二天客户打开系统发现昨天录的 200 条工单没了,你猜会不会被请去喝茶。
真实项目里,数据住在哪?数据库(Database)。
数据库听着高深,其实你可以把它理解成一个**"超级 Excel"**:
-
表(Table)≈ Sheet(工作表)
-
一行 ≈ 一条记录
-
一列 ≈ 一个字段
-
SQL ≈ 你跟这个超级 Excel 说话的语言
区别在于:Excel 几万行就卡,数据库几千万行不慌;Excel 一人编辑,数据库支持成百上千人同时读写;Excel 用 Ctrl+F 找数据,数据库用 SQL 精确查询。
💡 FDE 现场最常见的场景:客户甩给你一个 Excel 导出的 CSV,你把它导入数据库,然后用 SQL 做分析、清洗、对接。今天学的就是这套流程的第一步。
今天我们用 SQLite 上手------它是 Python 自带的,零安装,一个文件就是一个数据库,最适合学习。周五再切换到企业标配的 MySQL。
📖 一、三大数据库速览:SQLite / MySQL / PostgreSQL
先认识一下数据库家族的三兄弟,别到时候客户说用啥你都没听过:
┌──────────────────────────────────────────────────────────────┐
│ SQLite 🪶 轻量级 │
│ · 一个 .db 文件就是一个完整数据库 │
│ · 零安装、零配置、Python 自带(import sqlite3) │
│ · 适合:学习、原型开发、手机 App、单机小工具 │
│ · 短板:不支持多人高并发,不适合做生产服务器 │
│ │
│ MySQL 🐬 最流行 │
│ · 开源、免费、性能好、生态最成熟 │
│ · 企业标配,互联网公司十有八九在用 │
│ · 需要安装服务、配置账号密码 │
│ · 适合:Web 应用后端、FDE 交付主战场 │
│ │
│ PostgreSQL 🐘 功能最强 │
│ · 开源界的"学霸",支持复杂查询、JSON、地理空间 │
│ · 近几年越来越火 │
│ · 学习曲线稍陡 │
│ · 适合:复杂数据分析、金融、GIS │
└──────────────────────────────────────────────────────────────┘
📅 本周路线:
Day31-34 用 SQLite 学语法(免安装,专注 SQL 本身)
↓
Day35 切换 MySQL,接进真实项目(语法 95% 通用)
📌 核心认知 :SQL 是一门标准语言,三大数据库的 SQL 语法 90% 以上相通。今天在 SQLite 学的
SELECT ... WHERE ...,到 MySQL、PostgreSQL 照样能用。换数据库主要是换"连接方式",不是重学一门语言。
数据库 vs Excel 对照表
| 对比项 | Excel | 数据库(如 MySQL) |
|---|---|---|
| 数据组织 | Sheet(工作表) | Table(表) |
| 一行数据 | 一行 | 一条记录(Record / Row) |
| 一列 | 一列 | 一个字段(Field / Column) |
| 查找 | Ctrl+F / 筛选 | SQL 语句 |
| 多表关联 | VLOOKUP(写到崩溃) | JOIN(清爽) |
| 并发 | 一人编辑,别人只读 | 成百上千人同时读写 |
| 数据量 | 几万行开始卡 | 几千万行不慌 |
| 数据安全 | 删了就没了 | 事务、备份、回滚 |
🖥️ 二、实操:创建第一个 SQLite 数据库
这块是基础常识,懂的朋友直接跳过也行------不过第一次接触 sqlite3 的话,跟着敲一遍心里踏实。
步骤 1:建好练习目录
打开 VS Code,在你的工作区新建一个文件夹 sql_practice,然后新建文件 01_create_db.py。
步骤 2:写代码建库建表
"""
创建第一个 SQLite 数据库
文件:01_create_db.py
"""
import sqlite3
# ① 连接数据库
# 文件不存在会自动创建,存在就直接打开
conn = sqlite3.connect("fde_workshop.db")
cursor = conn.cursor() # cursor(游标)是执行 SQL 的"遥控器"
# ② 建表:设备信息表
# IF NOT EXISTS = 表不存在才建,已存在就跳过(防止重复运行报错)
cursor.execute("""
CREATE TABLE IF NOT EXISTS devices (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
type TEXT NOT NULL,
temperature REAL DEFAULT 0,
vibration REAL DEFAULT 0,
is_running INTEGER DEFAULT 1,
owner TEXT DEFAULT '未分配',
created_at TEXT DEFAULT (datetime('now', 'localtime'))
)
""")
# ③ 插入 5 条设备数据
devices_data = [
("注塑机A1", "注塑", 65, 8, 1, "李工"),
("注塑机A2", "注塑", 82, 12, 1, "王工"),
("注塑机A3", "注塑", 91, 16, 1, "赵工"),
("冲压机B1", "冲压", 75, 9, 0, "李工"),
("冲压机B2", "冲压", 88, 6, 1, "陈工"),
]
cursor.executemany("""
INSERT INTO devices (name, type, temperature, vibration, is_running, owner)
VALUES (?, ?, ?, ?, ?, ?)
""", devices_data)
# ④ 提交 + 验证 + 关闭
conn.commit() # ⚠️ 不 commit,数据不会真正写进文件
print(f"✅ 建表成功,插入了 {len(devices_data)} 条设备数据")
cursor.execute("SELECT COUNT(*) FROM devices")
print(f"当前设备总数:{cursor.fetchone()[0]}")
conn.close()
步骤 3:运行并观察
在 VS Code 终端执行:
python 01_create_db.py
预期输出:
✅ 建表成功,插入了 5 条设备数据
当前设备总数:5
再看 sql_practice 文件夹------多了一个 fde_workshop.db 文件。这就是你的数据库,全部数据都在里面。
步骤 4:拆解建表语句(看懂每个字段)
CREATE TABLE devices (
id INTEGER PRIMARY KEY AUTOINCREMENT, -- 主键:每条记录的唯一身份证号
name TEXT NOT NULL, -- NOT NULL:这列必填,不能空着
temperature REAL DEFAULT 0, -- REAL:小数;DEFAULT 0:不填就默认 0
is_running INTEGER DEFAULT 1 -- SQLite 没有真正的布尔,用 1/0 表示
)
SQLite 常用数据类型,给你理清楚:
| 类型 | 含义 | 对应 Python | 例子 |
|---|---|---|---|
INTEGER |
整数 | int |
1、65、-3 |
REAL |
小数(浮点数) | float |
82.5、0.0 |
TEXT |
文本字符串 | str |
"注塑机A1" |
BLOB |
二进制数据 | bytes |
图片、文件 |
NULL |
空值 | None |
未知、没填 |
📌 几个必须懂的关键词:
主键(PRIMARY KEY):每行数据的唯一编号,不能重复、不能空。就像身份证号,靠它精准定位一条记录。
AUTOINCREMENT:自增。插入时不用给 id,数据库自动 1、2、3......往下排。
NOT NULL:这一列必须有值,插入时不给就报错。
⚠️ 关键安全细节 :代码里的
?是参数占位符 。SQLite 用?,MySQL 用%s。绝对不要用字符串拼接 SQL("... VALUES ('" + name + "')"),那是 SQL 注入漏洞的根源------黑客能靠一个引号删光你的表。这个坑周五用 SQLAlchemy 时会再加固。
🖥️ 三、SELECT 查询三板斧:选字段、筛条件、排序分页
数据进去了,接下来是重头戏------把数据查出来。SQL 里 80% 的操作都是 SELECT。
新建 02_select.py:
"""
SELECT 查询三板斧:选字段、筛条件、排序分页
文件:02_select.py
"""
import sqlite3
conn = sqlite3.connect("fde_workshop.db")
conn.row_factory = sqlite3.Row # 让查询结果能像字典一样 row['name'] 取值
cursor = conn.cursor()
def show(title, sql):
"""跑 SQL 并打印结果的小工具"""
print(f"\n===== {title} =====")
cursor.execute(sql)
for row in cursor.fetchall():
print(" " + " | ".join(str(v) for v in tuple(row)))
# ① 基础查询:选哪些字段(* 表示全部列,生产中建议写明列名)
show("所有设备(只看4列)",
"SELECT id, name, temperature, owner FROM devices")
# ② WHERE:条件筛选
show("温度超过 80 的设备",
"SELECT name, temperature FROM devices WHERE temperature > 80")
# ③ AND:多条件同时满足
show("注塑机 且 在运行",
"""SELECT name, temperature FROM devices
WHERE type = '注塑' AND is_running = 1""")
# ④ IN:在一个名单里
show("负责人是李工或王工",
"SELECT name, owner FROM devices WHERE owner IN ('李工', '王工')")
# ⑤ BETWEEN:在某个区间(含两端)
show("温度在 70~90 之间",
"SELECT name, temperature FROM devices WHERE temperature BETWEEN 70 AND 90")
# ⑥ LIKE:模糊匹配(% 代表任意多个字符)
show("名字里含 A 的",
"SELECT name FROM devices WHERE name LIKE '%A%'")
# ⑦ ORDER BY + LIMIT:排序后取前 N 个
show("温度从高到低,前 3 名",
"""SELECT name, temperature FROM devices
ORDER BY temperature DESC
LIMIT 3""")
conn.close()
运行 python 02_select.py,对照下面的预期结果检查:
===== 温度超过 80 的设备 =====
注塑机A2 | 82.0
注塑机A3 | 91.0
冲压机B2 | 88.0
===== 温度从高到低,前 3 名 =====
注塑机A3 | 91.0
冲压机B2 | 88.0
注塑机A2 | 82.0
SELECT 语句的完整长相
SELECT 列名 -- 要哪些列(* = 全部)
FROM 表名 -- 从哪张表
WHERE 条件 -- 筛哪些行
ORDER BY 列名 DESC -- 怎么排序(DESC降序 / ASC升序,默认ASC)
LIMIT 数量 -- 只返回前几行
WHERE 条件操作符速查表
这张表建议截图存手机,写 SQL 时天天查:
| 操作符 | 含义 | 例子 | 能匹配到什么 |
|---|---|---|---|
= |
等于 | type = '注塑' |
类型正好是注塑 |
!= 或 <> |
不等于 | is_running != 1 |
没在运行的 |
> < >= <= |
大小比较 | temperature > 80 |
温度超 80 |
BETWEEN a AND b |
区间 | temperature BETWEEN 70 AND 90 |
70 到 90(含 70 和 90) |
IN (...) |
在列表中 | owner IN ('李工','王工') |
负责人是李或王 |
LIKE |
模糊匹配 | name LIKE '%A%' |
名字含 A |
IS NULL |
是空值 | owner IS NULL |
负责人没填 |
IS NOT NULL |
不是空值 | phone IS NOT NULL |
有手机号的 |
💡 LIKE 通配符两个兄弟:
%匹配任意多个 字符(包括 0 个):'A%'= 以 A 开头,'%A'= 以 A 结尾,'%A%'= 含 A
_匹配恰好一个 字符:'A_'匹配 "A1" 但不匹配 "A12"
⚠️ 注意 NULL 不能用
=判断 !WHERE phone = NULL永远查不到东西,必须写WHERE phone IS NULL。因为 NULL 表示"未知",未知不等于未知。
🖥️ 四、INSERT / UPDATE / DELETE:增、改、删
查询是"读",接下来是"写"三件套。新建 03_crud.py:
"""
INSERT / UPDATE / DELETE 增删改
文件:03_crud.py
"""
import sqlite3
conn = sqlite3.connect("fde_workshop.db")
cursor = conn.cursor()
# ① INSERT:新增一条
cursor.execute("""
INSERT INTO devices (name, type, temperature, vibration, is_running, owner)
VALUES ('注塑机A4', '注塑', 70, 7, 1, '赵工')
""")
conn.commit()
print(f"✅ 新增注塑机A4,自动分配的 id = {cursor.lastrowid}")
# ② UPDATE:修改(⚠️ 一定、一定、一定加 WHERE!)
cursor.execute("""
UPDATE devices
SET temperature = 95, is_running = 1
WHERE name = '注塑机A4'
""")
conn.commit()
print("✅ 注塑机A4 温度更新为 95")
# ③ DELETE:删除(⚠️ 更要加 WHERE!)
cursor.execute("DELETE FROM devices WHERE name = '注塑机A4'")
conn.commit()
print("✅ 注塑机A4 已删除")
# 验证:数量应该还是 5
cursor.execute("SELECT COUNT(*) FROM devices")
print(f"当前设备总数:{cursor.fetchone()[0]}")
conn.close()
三条语句的语法骨架,记住这个模板:
-- 增:往哪张表、哪些列、塞什么值
INSERT INTO 表名 (列1, 列2) VALUES (值1, 值2);
-- 改:改哪张表、改成啥、改哪些行
UPDATE 表名 SET 列1 = 新值 WHERE 条件;
-- 删:删哪张表的哪些行
DELETE FROM 表名 WHERE 条件;
🚨 头号生产事故:忘加 WHERE 的 UPDATE / DELETE
这是每个 DBA 和后端工程师的噩梦,单独拎出来红字警告:
❌ DELETE FROM devices; -- 整张表瞬间清空!连后悔药都没有!
❌ UPDATE devices SET owner='X'; -- 全表所有设备的负责人都变成 X!
✅ DELETE FROM devices WHERE id = 6; -- 只删 id=6 这一条
✅ UPDATE devices SET temperature=95
WHERE name = '注塑机A4'; -- 只改 A4
📌 FDE 保命操作规范 :在客户的生产数据库执行 UPDATE / DELETE 之前,先用一模一样的 WHERE 写一条 SELECT 跑一遍:
-- 第一步:先查,确认这些行就是你要动的 SELECT * FROM devices WHERE name = '注塑机A4'; -- 第二步:确认无误,再把 SELECT * 换成 DELETE / UPDATE DELETE FROM devices WHERE name = '注塑机A4';多花 10 秒钟,能保住你一份工作。
为什么 INSERT/UPDATE/DELETE 后要 commit?
你的代码 数据库文件
─────── ──────────
cursor.execute(INSERT) → 改动只在"草稿区"(事务)
此时别人查不到、断电就没
conn.commit() → ✅ 正式落盘,改动生效
conn.close() 没 commit → ❌ 草稿丢弃,白干
这叫**事务(Transaction)**机制。好处是:你连着做了 5 个操作,中途出错可以整体回滚,不会留下半截脏数据。周五会细讲。
🖥️ 五、装个可视化工具 DBeaver:用图形界面看数据库
老在 Python 里拼 SQL 字符串不够直观。推荐一个免费神器 DBeaver,几乎支持所有数据库。
安装步骤
-
打开 Download | DBeaver Community ,下载 Community Edition(免费开源版)
-
一路下一步安装,打开它
-
点左上角"新建连接"(插头图标)→ 选择 SQLite → 下一步
-
"Path" 那栏浏览选中你的
fde_workshop.db文件 → 点"完成" -
左侧展开连接 → 展开 Tables → 双击
devices表 → 切到"数据"标签页
你会看到数据整整齐齐躺在表格里,跟 Excel 几乎一样。
在 DBeaver 里直接写 SQL
-
右键
devices表 → "SQL 编辑器" → "新建 SQL 脚本" -
输入:
SELECT name, temperature, owner
FROM devices
WHERE temperature > 80
ORDER BY temperature DESC; -
按 Ctrl + Enter(或点橙色执行按钮)→ 下方立刻出结果
💡 DBeaver 的杀手锏:自动补全 + 语法高亮 。你敲
SEL它提示SELECT,敲表名提示列名。学习 SQL 阶段,强烈建议在 DBeaver 里练查询,比在 Python 里拼字符串舒服 10 倍。熟练后再回到代码里。
📝 本课小结
| 知识点 | 一句话记住 |
|---|---|
| 数据库 | 超级 Excel,数据持久保存,重启不丢 |
| SQLite | 一个 .db 文件 = 一个数据库,Python 自带 |
| 数据类型 | INTEGER 整数 / REAL 小数 / TEXT 文本 / NULL 空 |
| 主键 | 每行的唯一身份证,PRIMARY KEY AUTOINCREMENT 自增 |
| SELECT | 选字段,配 WHERE 筛选、ORDER BY 排序、LIMIT 限量 |
| WHERE | = > IN BETWEEN LIKE IS NULL |
| INSERT | INSERT INTO 表(列) VALUES(值) |
| UPDATE | UPDATE 表 SET 列=值 WHERE 条件,必须加 WHERE |
| DELETE | DELETE FROM 表 WHERE 条件,更必须加 WHERE |
| commit | 写操作后必须 commit,否则改动不落盘 |
| 占位符 | SQLite 用 ?,防 SQL 注入,别拼字符串 |
| DBeaver | 免费的数据库图形化工具,练 SQL 神器 |
🧠 核心认知 :SQL 操作分两大类------读(SELECT)和写(INSERT/UPDATE/DELETE)。读随便试,查错了不会坏数据;写要敬畏,尤其 UPDATE/DELETE,先 SELECT 确认再动手。
📋 课后练习
练习 1:在 DBeaver 里写 10 道查询(约 40 分钟)
用 SQL 编辑器完成,每道题先自己想再敲:
-
查所有运行中的设备(
is_running = 1) -
查温度最高的 3 台设备
-
查负责人不是 "李工"的设备(提示
!=) -
查振动值在 8~12 之间的设备
-
查所有设备名和温度,按温度从低到高 排(
ASC) -
新增一台设备"焊接机C1"(类型填"焊接",其他值自己定)
-
把"注塑机A3"的温度改成 85
-
删除你刚新增的"焊接机C1"(先 SELECT 确认再 DELETE)
-
统计设备总数(提示:
SELECT COUNT(*) FROM devices) -
查所有停机的设备(
is_running = 0),看看是哪台
练习 2:写个可复用的查询脚本(约 20 分钟)
新建 query_devices.py,接收一个温度阈值参数,打印超过该温度的设备:
python query_devices.py 80
# 输出温度 > 80 的所有设备
提示:用 sys.argv[1] 拿参数,记得转成 float,SQL 里用 ? 占位符传参。
🔭 下节预告
今天我们一直在一张表 里折腾。但真实业务里,设备信息、工程师档案、工单记录是分开存在好几张表里的------为什么要拆?拆开以后怎么一起查?
明天学两个 FDE 数据查询的核心技能:**JOIN(把多张表拼起来查)**和 GROUP BY(分组统计)。比如"每个车间有几台设备、平均温度多少",明天一行 SQL 搞定。今天的单表是地基,明天才是数据库真正的威力所在,养好精神,明天见!
🌍附录:前置课程列表
阶段一:
【FDE系列】阶段1Day 1:AI 层级关系 --- 四个嵌套的圈-CSDN博客
【FDE系列】阶段1Day 2:AI 三阶段发展史 --- 会认 → 会判断 → 会创造-CSDN博客
【FDE系列】阶段1Day 3:符号 AI vs 机器学习 --- 两条路线的本质区别-CSDN博客
【FDE系列】阶段1Day 4:Transformer 的历史意义 --- 2017 年的分水岭-CSDN博客
【FDE系列】阶段1Day 5:本周复习与自测 --- 检验你的 AI 认知地基-CSDN博客
【FDE系列】阶段1Day 6:Transformer 架构 --- 一张图纸盖出千千万万栋楼-CSDN博客
【FDE系列】阶段1Day 7:LLM 本质 --- 文字接龙机器-CSDN博客
【FDE系列】阶段1Day 8:Token --- 模型眼中的最小单位-CSDN博客
【FDE系列】阶段1Day 9:AI 幻觉 --- 为什么会一本正经地胡说八道-CSDN博客
【FDE系列】阶段1Day 10:上下文窗口 --- 模型的记忆力上限 + 本周复习-CSDN博客
【FDE系列】阶段1Day 11:Prompt --- 给模型立规矩-CSDN博客
【FDE系列】阶段1Day 12:Memory --- 让模型记住上下文
【FDE系列】阶段1Day 13:RAG --- 给模型配图书管理员-CSDN博客
【FDE系列】阶段1Day 14:Tool Use --- 让模型动手操作-CSDN博客
【FDE系列】阶段1Day 15:MCP --- 统一的工具接口标准 + 第三周复习-CSDN博客
【FDE系列】阶段1Day 16:什么是 FDE --- 把 AI 变成客户结果的人-CSDN博客
【FDE系列】阶段1Day 17:FDE vs 传统实施 --- 三大本质区别-CSDN博客
【FDE系列】阶段1Day 18:FDE 三重身份 + C6 胜任力模型-CSDN博客
【FDE系列】阶段1Day 19:七阶段行动路径 + 行业经验的价值-CSDN博客
【FDE系列】阶段1Day 20:阶段总结与产出物 --- 第一阶段收官-CSDN博客
阶段二:
【FDE系列】阶段2:Day 21:Python 环境搭建 --- 写出你的第一行代码-CSDN博客
【FDE系列】阶段2:Day 22:变量、数据类型、条件判断 --- Python 的"记忆"和"判断"-CSDN博客
【FDE系列】阶段2:Day 23:循环与函数 --- 让代码跑 100 遍、把逻辑打包复用-CSDN博客
【FDE系列】阶段2:Day 24:数据结构 --- 列表、字典、集合、元组-CSDN博客
【FDE系列】阶段2:Day 25:文件读写与 JSON --- 让程序连通外部数据(第一周收官)-CSDN博客
【FDE系列】阶段2:Day 26:模块化编程 --- 把代码拆成"抽屉柜"-CSDN博客
【FDE系列】阶段2:Day 27:异常处理与日志 --- 让程序"摔不烂、查得到"-CSDN博客
【FDE系列】阶段2:Day 28:FastAPI 入门 --- 把你的函数变成 API 服务-CSDN博客
【FDE系列】阶段2:Day 29:FastAPI 进阶 --- Pydantic 模型与完整 CRUD 实战-CSDN博客