第5章 5.1 MySQL 基础与数据库入门(Python 版)
🎯 开场:为什么你的程序需要"仓库"?
想象一下:你开了一家奶茶店,每天卖多少杯、谁买的、几点买的……全记在脑子里。第一天 10 个顾客你能记住,第三天 100 个订单你就蒙了。
程序也一样——用户注册的信息、订单数据、配置参数……全存在变量里?程序一关全没了。
这就是数据库存在的意义:给程序找一个永久存放数据的地方。
你上一章(4.5 登录注册系统)把用户数据存在数组里,刷新页面就丢了,对吧?这一章我们来解决这个问题——学会用 MySQL 这个"超级 Excel",让你的程序记住用户的数据。
学完本文,你将能:
- 说出 MySQL 和 SQL 是什么关系
- 用 Python 连上 MySQL 数据库
- 完成"增删改查"基本操作
- 用可视化工具 phpMyAdmin 看懂你的数据
🧱 基础:3 个核心概念(25 分钟)
什么是数据库?—— 比喻篇
数据库(Database) = 一个仓库,里面有很多\n\n
\n\n
\n\n柜子(表)。
| 生活例子 | 技术对应 |
|---|---|
| 一栋大楼 | MySQL 服务器 |
| 大楼的某一层 | 一个 Database |
| 这一层的柜子 | Database 里的 Table(表) |
| 柜子里的文件 | Table 里的数据行(Record) |
SQL(Structured Query Language) = 仓库管理员的"指令手册",用来告诉数据库你要做什么。
为什么要用 MySQL?
- 免费开源:不花钱,足够强大
- 速度快:处理百万级数据毫无压力
- 全世界的网站:Facebook、Twitter、YouTube 都在用
- 配套工具多:phpMyAdmin 就是其中之一,一个网页版的"数据库控制台"
怎么用?先安装!(Mac 用户看这里)
方法一:Homebrew(一键安装)
brew install mysql
brew install --cask phpmyadmin
方法二:MAMP(推荐新手)
下载 MAMP(免费版),安装后自带 MySQL + phpMyAdmin,点一下"Start"就启动了。
说白了:MySQL 是"仓库",phpMyAdmin 是"仓库管理界面",让你不用记命令也能操作仓库。
🎉 第一个 MySQL 命令(5 分钟上手)
打开终端,连上 MySQL:
mysql -u root -p
输入密码后,你会看到这样的提示符:
mysql>
创建一个"奶茶店数据库":
CREATE DATABASE milktea_shop;
USE milktea_shop;
创建一个"订单表":
CREATE TABLE orders (
id INT AUTO_INCREMENT PRIMARY KEY,
customer_name VARCHAR(50),
drink VARCHAR(50),
price DECIMAL(10,2),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
插入一条数据:
INSERT INTO orders (customer_name, drink, price) VALUES ('小明', '珍珠奶茶', 18.5);
查看数据:
SELECT * FROM orders;
预期输出:
+----+---------------+-----------+-------+---------------------+
| id | customer_name | drink | price | created_at |
+----+---------------+-----------+-------+---------------------+
| 1 | 小明 | 珍珠奶茶 | 18.50 | 2024-01-15 10:30:00 |
+----+---------------+-----------+-------+---------------------+
一句话解释:这就是 SQL——用类似英语的语句,告诉数据库"我要查/增/改/删"数据。
Python 怎么连 MySQL?
终于到 Python 了!用 mysql-connector-python 这个库:
安装:
pip install mysql-connector-python
连接数据库(3 行搞定):
import mysql.connector
conn = mysql.connector.connect(
host="localhost",
user="root",
password="你的密码",
database="milktea_shop"
)
cursor = conn.cursor()
print("连接成功!")
查询数据:
cursor.execute("SELECT * FROM orders")
results = cursor.fetchall()
for row in results:
print(f"顾客:{row[1]},饮品:{row[2]},价格:{row[3]}元")
预期输出:
顾客:小明,饮品:珍珠奶茶,价格:18.5元
插入数据(带参数防注入):
sql = "INSERT INTO orders (customer_name, drink, price) VALUES (%s, %s, %s)"
values = ("小红", "椰果奶茶", 20.0)
cursor.execute(sql, values)
conn.commit() # 重要!不提交就不会存进去
print(f"插入成功,ID:{cursor.lastrowid}")
注意!:Python 字符串拼 SQL 很危险(会被黑客攻击),后面 5.2 章我们会详细讲预处理语句。
CRUD 完整操作一览
import mysql.connector
conn = mysql.connector.connect(
host="localhost",
user="root",
password="你的密码",
database="milktea_shop"
)
cursor = conn.cursor()
# ===== Create(增) =====
cursor.execute("INSERT INTO orders (customer_name, drink, price) VALUES ('小刚', '柠檬茶', 15.0)")
conn.commit()
# ===== Read(查) =====
cursor.execute("SELECT * FROM orders WHERE price > 15")
for row in cursor.fetchall():
print(row)
# ===== Update(改) =====
cursor.execute("UPDATE orders SET price = 22.0 WHERE customer_name = '小刚'")
conn.commit()
# ===== Delete(删) =====
cursor.execute("DELETE FROM orders WHERE customer_name = '小刚'")
conn.commit()
conn.close()
一句记住 CRUD:「查」单词是 SELECT,「增」是 INSERT,「改」是 UPDATE,「删」是 DELETE——都是英语,不用背,看多了就认识。
🔥 实战:3 个递进小项目(35 分钟)
项目 1:Python 读取数据库(5 分钟)
目标:把 phpMyAdmin 里的数据显示在 Python 控制台。
完整代码:
import mysql.connector
# 连接数据库
conn = mysql.connector.connect(
host="localhost",
user="root",
password="你的密码",
database="milktea_shop"
)
cursor = conn.cursor()
# 查询所有订单
cursor.execute("SELECT * FROM orders")
orders = cursor.fetchall()
print("=" * 40)
print(" 奶茶店订单报表")
print("=" * 40)
total = 0
for order in orders:
order_id, name, drink, price, time = order
print(f"订单{order_id} | {name} | {drink} | {price}元")
total += price
print("-" * 40)
print(f"今日营收:{total} 元")
print("=" * 40)
conn.close()
预期输出:
========================================
奶茶店订单报表
========================================
订单1 | 小明 | 珍珠奶茶 | 18.5元
订单2 | 小红 | 椰果奶茶 | 20.0元
----------------------------------------
今日营收:38.5 元
========================================
一句话解释:用
fetchall()一次取出所有行,遍历打印。
项目 2:CSV 数据批量导入(15 分钟)
背景:你的奶茶店搞活动,从大众点评导出了一份 CSV 格式的顾客反馈,要存到数据库里。
feedback.csv 内容:
customer_name,drink,price,rating
小王,芝芝芒芒,32.0,5
小李,芋泥波波,28.0,4
小张,杨枝甘露,30.0,5
小赵,奥利奥奶茶,25.0,3
小周,茉莉奶绿,22.0,4
Python 批量导入脚本:
import mysql.connector
import csv
conn = mysql.connector.connect(
host="localhost",
user="root",
password="你的密码",
database="milktea_shop"
)
cursor = conn.cursor()
# 创建新表存储评分
cursor.execute("""
CREATE TABLE IF NOT EXISTS feedback (
id INT AUTO_INCREMENT PRIMARY KEY,
customer_name VARCHAR(50),
drink VARCHAR(50),
price DECIMAL(10,2),
rating INT
)
""")
# 读取 CSV 并插入数据库
with open('feedback.csv', 'r', encoding='utf-8') as f:
reader = csv.DictReader(f) # 把 CSV 读成字典列表
for row in reader:
sql = "INSERT INTO feedback (customer_name, drink, price, rating) VALUES (%s, %s, %s, %s)"
values = (row['customer_name'], row['drink'], float(row['price']), int(row['rating']))
cursor.execute(sql, values)
conn.commit()
# 验证:查询评分大于等于4的订单
print("评分 4 星以上的订单:")
cursor.execute("SELECT * FROM feedback WHERE rating >= 4")
for row in cursor.fetchall():
print(f" {row[1]}点了{row[2]},给了{row[4]}星好评!")
conn.close()
print("\n导入完成!")
预期输出:
评分 4 星以上的订单:
小王点了芝芝芒芒,给了5星好评!
小李点了芋泥波波,给了4星好评!
小张点了杨枝甘露,给了5星好评!
小周点了茉莉奶绿,给了4星好评!
导入完成!
一句话解释:
csv.DictReader帮你把 CSV 每行转成字典,%s占位符防止 SQL 注入。
项目 3:简易销售统计工具(15 分钟)
目标:做一个命令行工具,统计本周卖得最好的饮品。
import mysql.connector
from collections import Counter
conn = mysql.connector.connect(
host="localhost",
user="root",
password="你的密码",
database="milktea_shop"
)
cursor = conn.cursor()
def show_stats():
print("\n" + "=" * 40)
print(" 🧋 奶茶店销售统计")
print("=" * 40)
# 1. 总订单数
cursor.execute("SELECT COUNT(*) FROM orders")
total_orders = cursor.fetchone()[0]
print(f"📦 总订单数:{total_orders}")
# 2. 总营收
cursor.execute("SELECT SUM(price) FROM orders")
total_revenue = cursor.fetchone()[0] or 0
print(f"💰 总营收:{total_revenue} 元")
# 3. 最热门的饮品
cursor.execute("SELECT drink FROM orders")
drinks = [row[0] for row in cursor.fetchall()]
if drinks:
counter = Counter(drinks)
top_drink, count = counter.most_common(1)[0]
print(f" 🔥 最受欢迎:{top_drink}({count} 单)")
# 4. 列出所有订单
print("\n📋 最近订单:")
cursor.execute("SELECT * FROM orders ORDER BY created_at DESC LIMIT 5")
for row in cursor.fetchall():
print(f" {row[4].strftime('%m-%d %H:%M')} | {row[1]} | {row[2]} | {row[3]}元")
print("=" * 40)
# 插入今天的订单演示
demo_orders = [
("小孙", "生椰拿铁", 28.0),
("小吴", "珍珠奶茶", 18.5),
("小郑", "生椰拿铁", 28.0),
]
for name, drink, price in demo_orders:
cursor.execute("INSERT INTO orders (customer_name, drink, price) VALUES (%s, %s, %s)",
(name, drink, price))
conn.commit()
show_stats()
conn.close()
预期输出:
========================================
🧋 奶茶店销售统计
========================================
📦 总订单数:5
💰 总营收:121.5 元
🔥 最受欢迎:生椰拿铁(2 单)
📋 最近订单:
1-15 14:30 | 小郑 | 生椰拿铁 | 28.0元
1-15 14:29 | 小吴 | 珍珠奶茶 | 18.5元
1-15 14:28 | 小孙 | 生椰拿铁 | 28.0元
========================================
一句话解释:
Counter来自collections模块,帮你数出场次最高的元素。
💪 进阶:4 个坑 + 1 个技巧(20 分钟)
坑 1:忘记 commit()
# ❌ 错误:数据没存进去
cursor.execute("INSERT INTO orders (customer_name, drink, price) VALUES ('测试', '绿茶', 15)")
# 没有 commit()
# ✅ 正确:养成习惯,insert/update/delete 后立刻 commit
cursor.execute("INSERT INTO orders (customer_name, drink, price) VALUES ('测试', '绿茶', 15)")
conn.commit()
坑 2:中文字符乱码
# ❌ 错误:不指定字符集,遇到中文就变成 ???
conn = mysql.connector.connect(
host="localhost",
user="root",
password="密码"
)
# ✅ 正确:加上 charset='utf8mb4'(支持所有 Unicode 字符)
conn = mysql.connector.connect(
host="localhost",
user="root",
password="密码",
charset='utf8mb4'
)
坑 3:SQL 字符串拼接(会中毒!)
# ❌ 错误:用户输入 "'; DROP TABLE orders; --" 你的数据库就没了!
user_input = "' OR 1=1 --"
cursor.execute(f"SELECT * FROM users WHERE name = '{user_input}'")
# ✅ 正确:用参数化查询(下一章 5.2 会深入讲)
sql = "SELECT * FROM users WHERE name = %s"
cursor.execute(sql, (user_input,))
坑 4:关闭连接顺序
# ❌ 错误:先关 cursor 再关 conn,可能丢失未提交的数据
cursor.close()
conn.close() # 如果刚才有插入没 commit,数据就没了
# ✅ 正确:先 commit,再关 cursor,最后关 conn
conn.commit()
cursor.close()
conn.close()
坑 5:查不到数据不报错
# ❌ 错误:以为查不到数据会返回 None 或空列表
cursor.execute("SELECT * FROM orders WHERE id = 9999")
result = cursor.fetchone()
print(result) # 返回 None,不会报错,但如果你不检查就直接用 result[0],会崩溃
# ✅ 正确:养成检查习惯
result = cursor.fetchone()
if result:
print(result)
else:
print("没有找到这个订单")
调试技巧:用 %s 打印变量
# 复杂查询前,先打印出来看看对不对
sql = "SELECT * FROM orders WHERE customer_name = %s AND price > %s"
values = ("小明", 20)
# 打印最终的 SQL 语句(调试用)
print(f"执行SQL: {sql},参数: {values}")
cursor.execute(sql, values)
调试一句话:先打印,再执行,发现问题早处理。
✏️ 练习题 + 作业题(共 7 分钟)
练习题(5 道,10 分钟)
练习 1(1 分钟):改名字
- 输入:在项目 1 代码里,把 customer_name 改成 username
- 预期输出:正常打印(字段名变了,输出文字相应变化)
- 提示:SELECT * 会选所有列,但打印时要改成对应的列索引
练习 2(2 分钟):加个判断
- 输入:在项目 1 的循环里,加一个 if 判断,只打印价格 > 20 的订单
- 预期输出:只打印贵的订单
- 提示:if order[3] > 20:(price 是第 4 列,索引是 3)
练习 3(2 分钟):新 CSV
- 输入:创建一个 students.csv,包含 name,score 两列,3 行数据,用项目 2 的方法导入
- 预期输出:打印所有导入的数据
- 提示:表结构改成 id INT, name VARCHAR(50), score INT
练习 4(3 分钟):串项目 2+3
- 输入:用项目 2 的方法从 CSV 导入数据到 feedback 表,然后用项目 3 的 Counter 统计哪种饮品最受欢迎
- 预期输出:打印最受欢迎的饮品名称
- 提示:导入数据和统计分开做,先插入再查询
练习 5(2 分钟):找错
- 输入:以下代码运行报错 IndexError: tuple index out of range,找原因
cursor.execute("SELECT drink FROM orders")
result = cursor.fetchone()
print(result[1]) # 报错行
- 预期输出:说明哪里错了,怎么改
- 提示:
fetchone()返回 1 行,不是多行
作业题(30 分钟 - 2 小时)
作业:做一个「个人收支记录工具」
- 需求:用 MySQL 存你的日常花销,Python 做个命令行界面查看统计
- 功能点:
1. 用 SQL 创建expenses表(字段:id, category, amount, note, date)
2. 用 Python 插入至少 5 条模拟收支数据
3. 查询本周支出总额
4. 按分类统计支出(餐饮/交通/购物/其他) - 加分项:
1. 支持按月份筛选查询
2. 用 phpMyAdmin 截图展示你的数据 - 验收标准:能跑起来 + 输出收支统计 + 代码有注释
- 提交方式:评论区贴代码或 GitHub 链接
📚 总结 + 资源(5 分钟)
一句话记住 3 个核心点
- MySQL 是仓库,SQL 是指令书——用
SELECT/INSERT/UPDATE/DELETE告诉数据库干什么 - Python 通过
mysql-connector-python操控数据库——连接 → 执行 → 提交 → 关闭 - 参数化查询防 SQL 注入——永远别用字符串拼接 SQL(下一章会深入讲)
延伸学习资源
- 官方文档:MySQL 8.0 Reference Manual(英文,但例子清晰)
- 视频教程:B 站「MySQL 入门」系列(选播放量最高的,1.5 倍速看)
- 工具推荐:DBeaver(免费的数据库客户端,比命令行好看)
互动钩子
你在工作/学习中用过数据库吗? 是记录用户、存订单、还是做数据分析?评论区聊聊你的使用场景,帮你想想怎么用今天学的知识解决实际问题!老粉优先回复 ~
下章预告:上一章我们学了登录注册,但密码明文存储太危险了……下一章「5.2 PDO 预处理与防 SQL 注入」会教你:怎么让黑客无法攻击你的数据库,以及预处理语句到底是什么「盾牌」?敬请期待!

评论(0)