🐍🔗

🔬 Python 连接 MySQL · 上机实验

💻 在自己电脑上真跑 Python + MySQL ⏱️ 预计 45 分钟 📦 配套讲义 第17章
🎯 这节课你要亲手做到
  • 跑通 5 步流程,让 Python 真正连上数据库
  • 写出带 try-except 的"增 / 改"程序,并提交成功
  • 用 fetch 把查询结果一行行打印出来
  • 亲眼见证:忘了 commit,数据真的会丢

这是一节动手课:每个任务都先自己写、自己跑,跑不出来再看提示,最后对参考答案。先扫一眼速查区,然后从环境准备开始 —— 这一步没做好,后面代码会连不上。👇

📌 动手前 · 30 秒速查

5 步标准模板(照着填)
import mysql.connector              # ① 导入
db = mysql.connector.connect(...)    # ② 连接
cursor = db.cursor()                 # ③ 游标
try:
    cursor.execute("...")            # ④ 执行
    db.commit()                      # 改数据要 commit
except:
    db.rollback()
cursor.close(); db.close()           # ⑤ 关闭

最容易丢分的三个坑

坑① 忘了 commit
增 / 改 / 删后不 commit,数据只在缓冲区,关掉就没了
坑② 不用 try-except
出错时数据可能"改了一半",用 try-except 兜底
坑③ fetch 用混
fetchone 给元组、fetchall 给列表,别拿错
0

环境准备:把"能连上"先搞定

三步:装包 → 建库建表 → 跑一个测试脚本确认通了

🛠️ 第一步:装连接包

命令行(不是 Python 里)运行下面这句。装完再用一行验证它能导入。

命令行
# 安装
pip install mysql-connector-python

# 验证:能打印出版本号就说明装好了
python -c "import mysql.connector; print(mysql.connector.__version__)"

🛠️ 第二步:建库、建表、灌数据

打开 Navicat / 命令行 / Workbench,把下面整段复制运行。所有任务都用这套 teaching 库里的 s 表。

SQL · 一键运行
-- 1. 建库并使用(讲义里的 connect 也连这个库)
CREATE DATABASE IF NOT EXISTS teaching DEFAULT CHARSET utf8mb4;
USE teaching;

-- 2. 重建学生表(先删后建,方便反复练习)
DROP TABLE IF EXISTS s;
CREATE TABLE s (
    sno  CHAR(5)     PRIMARY KEY,   -- 学号
    sn   VARCHAR(10) NOT NULL,      -- 姓名
    sex  CHAR(2),                    -- 性别
    age  INT,                        -- 年龄
    maj  VARCHAR(30),                -- 专业
    dept VARCHAR(30)                 -- 院系
);

-- 3. 灌入 10 条测试数据(男女、年龄、院系都有,方便后面各种查询)
INSERT INTO s VALUES
('s1', '王彤',  '女', 18, '计算机', '信息学院'),
('s2', '苏乐',  '女', 20, '信息',   '信息学院'),
('s3', '陶然',  '男', 19, '计算机', '信息学院'),
('s4', '何欣荣','女', 21, '软件',   '信息学院'),
('s5', '赵琳琳','女', 20, '数学',   '理学院'),
('s6', '林毅',  '男', 22, '信息',   '信息学院'),
('s7', '周杰',  '男', 18, '物理',   '理学院'),
('s8', '郑爽',  '女', 19, '数学',   '理学院'),
('s9', '孙俊',  '男', 21, '软件',   '信息学院'),
('s10','苏红霞','女', 20, '信息',   '信息学院');

🛠️ 第三步:跑一个连接测试脚本

新建一个 connect_test.py,把下面代码贴进去运行。能打印出版本和学生人数,就说明 Python 和 MySQL 接通了,可以开始做任务了。

Python · connect_test.py
import mysql.connector

db = mysql.connector.connect(
    host='localhost',
    user='root',
    passwd='123456',        # ← 改成你自己的 MySQL 密码
    database='teaching'
)
cursor = db.cursor()

cursor.execute("SELECT VERSION()")
print("数据库版本:", cursor.fetchone()[0])

cursor.execute("SELECT COUNT(*) FROM s")
print("学生人数:", cursor.fetchone()[0])

cursor.close()
db.close()
▶ 跑通后应该看到(人数是 10)数据库版本: 8.0.23 学生人数: 10
⚠️ 连不上?大多是这两点

passwd 写的不是你本机 MySQL 的真实密码;② MySQL 服务没启动。

OperationalError 基本就是这俩之一,先检查它们。

✅ 准备完成的标志

命令行能打印 connector 版本号;MySQL 里 SELECT * FROM s; 看到 10 个学生;connect_test.py 打印出版本和人数 10。三项都对,开始动手。

1

实验一 · 基础任务

人人都要会 —— 先把 5 步流程和 commit 跑顺
任务 1 ⭐ 基础 连接 + 查询

写一个程序,连上 teaching 数据库,查询学生总数并打印。这一关只为把 5 步流程跑通。

💡 卡住了?看这一条提示

① SQL 用 SELECT COUNT(*) FROM s

② 结果只有一行一个数,用 fetchone() 取。

③ 它返回的是元组 (10,),要用 [0] 取出数字。查询不用 commit

🎯 怎么验证

运行你的 .py,控制台应打印:

▶ 预期输出学生总数: 10
参考答案
Python
import mysql.connector

db = mysql.connector.connect(
    host='localhost', user='root',
    passwd='123456', database='teaching'
)
cursor = db.cursor()

cursor.execute("SELECT COUNT(*) FROM s")
result = cursor.fetchone()        # 返回元组,如 (10,)
print("学生总数:", result[0])

cursor.close()
db.close()

查询只是读,没有 commitfetchone()[0] 把元组里的数字取出来。

任务 2 ⭐ 基础 INSERT + commit

try-except 模板s 表插入一名新学生,提交后到 MySQL 里确认真的插进去了

要插入的数据
('s20', '陈小明', '男', 20, '软件', '信息学院')
💡 卡住了?看这一条提示

① 这是"改数据",套速查区那个 try-except 壳

try 里:execute(插入SQL) + db.commit()

except 里:db.rollback()

🎯 怎么验证

① 程序打印"插入成功";② 回到 MySQL 执行下面这句,能查到 s20:

SQL · 去数据库确认
SELECT * FROM s WHERE sno='s20';
▶ 你应该查到s20 陈小明 男 20 软件 信息学院
🔬 顺手做个小实验:见证 commit 的作用

这一步能让你一辈子记住为什么要 commit

① 先把 db.commit() 那行注释掉(前面加 #),改插一个新学号 's21',运行 —— 不会报错;

② 去 MySQL 查 SELECT * FROM s WHERE sno='s21'; —— 查不到!因为没提交;

③ 把注释去掉再跑一次,再查 —— 出现了。这就是"读不 commit,写必 commit"。

参考答案
Python
import mysql.connector

db = mysql.connector.connect(
    host='localhost', user='root',
    passwd='123456', database='teaching'
)
cursor = db.cursor()

try:
    cursor.execute("INSERT INTO s VALUES('s20','陈小明','男',20,'软件','信息学院')")
    db.commit()              # ⭐ 必须提交,数据才真的写入
    print("插入成功")
except Exception as e:
    db.rollback()            # 出错就撤销
    print("插入失败:", e)

cursor.close()
db.close()

"改数据"的黄金套路:try 里 execute + commit,except 里 rollback

2

实验二 · 提高任务

把"改"和"查"用熟 —— rowcount 和 fetch 一族
任务 3 ⭐⭐ 提高 UPDATE + rowcount

s 表里所有"信息学院"学生的年龄都 +1,并打印影响了多少行

💡 卡住了?看这一条提示

① SQL:UPDATE s SET age = age + 1 WHERE dept = '信息学院'

② 改数据,记得 commit + try-except。

③ 执行后看 cursor.rowcount,就是被改的行数。

🎯 怎么验证

原始数据里信息学院有 7 人(s1、s2、s3、s4、s6、s9、s10),所以:

▶ 预期输出成功更新 7 行

💡 注意:这条会真的改库。想恢复原样,重跑一遍环境准备第二步即可。

参考答案
Python
import mysql.connector

db = mysql.connector.connect(
    host='localhost', user='root',
    passwd='123456', database='teaching'
)
cursor = db.cursor()

sql = "UPDATE s SET age = age + 1 WHERE dept = '信息学院'"
try:
    cursor.execute(sql)
    db.commit()
    print("成功更新", cursor.rowcount, "行")
except Exception as e:
    db.rollback()
    print("更新失败:", e)

cursor.close()
db.close()

cursor.rowcount 返回上一次 execute 影响的行数,改 / 删时用它判断"到底动了几条"。

任务 4 ⭐⭐ 提高 SELECT + 遍历

查询 s 表里所有女生的学号和姓名,一行行打印,格式为 s1 | 王彤

💡 卡住了?看这一条提示

① SQL:SELECT sno, sn FROM s WHERE sex = '女'

② 用 fetchall() 取全部,得到一个列表。

for row in results: 里,row[0] 是学号、row[1] 是姓名。

🎯 怎么验证
▶ 预期输出(原始数据下,6 名女生)s1 | 王彤 s2 | 苏乐 s4 | 何欣荣 s5 | 赵琳琳 s8 | 郑爽 s10 | 苏红霞
参考答案
Python
import mysql.connector

db = mysql.connector.connect(
    host='localhost', user='root',
    passwd='123456', database='teaching'
)
cursor = db.cursor()

cursor.execute("SELECT sno, sn FROM s WHERE sex = '女'")
results = cursor.fetchall()      # 列表,每个元素是一行的元组

for row in results:
    print(row[0], "|", row[1])

cursor.close()
db.close()

也可以更优雅地解包:for sno, sn in results: print(sno, "|", sn)

🤔 顺手对比一下 fetch 三件套
把上面的 fetchall() 分别换成 fetchone()fetchmany(3),各跑一次,看看打印出来有什么不同 —— 你会直观感受到:一个给"一行",一个给"全部列表",一个给"前 3 行的列表"。
3

实验三 · 拓展任务

把整章揉一起 —— 一个连接里,增、改、查一条龙
任务 5 ⭐⭐⭐ 拓展 CRUD 综合

一个完整程序,在一次连接里依次完成下面几件事:

业务需求
插入一名新生 ('s30','王晓明','男',20,'计算机','信息学院')
修改"赵琳琳"的专业为"软件";
③ 上面两步用 try-except 包住,出错回滚;
查询并逐行打印所有"信息学院"的学生;
⑤ 最后关闭游标和连接。
💡 卡住了?看这一条提示

① 一次连接做三件事:INSERT、UPDATE 是"改",SELECT 是"查"。

② 把 INSERT + UPDATE 放进同一个 try,一起 commit —— 保证两步要么都成、要么都退。

SELECT 单独放在 try 外面,查询不需要事务保护。

🎯 怎么验证
▶ 预期输出(示意)插入和修改成功! --- 信息学院学生列表 --- ('s1', '王彤', '女', 18, '计算机', '信息学院') ('s2', '苏乐', '女', 20, '信息', '信息学院') ... (含刚插入的 s30) 程序执行完毕
参考答案
Python
import mysql.connector

# ① 连接
db = mysql.connector.connect(
    host='localhost', user='root',
    passwd='123456', database='teaching'
)
cursor = db.cursor()

# ② 改数据:INSERT + UPDATE 一起,用 try-except 保证原子性
try:
    cursor.execute("INSERT INTO s VALUES('s30','王晓明','男',20,'计算机','信息学院')")
    cursor.execute("UPDATE s SET maj='软件' WHERE sn='赵琳琳'")
    db.commit()
    print("插入和修改成功!")
except Exception as e:
    db.rollback()
    print("操作失败,已回滚:", e)

# ③ 查数据:单独执行,不需要事务
print("\n--- 信息学院学生列表 ---")
cursor.execute("SELECT * FROM s WHERE dept = '信息学院'")
for row in cursor.fetchall():
    print(row)

# ④ 关闭
cursor.close()
db.close()
print("\n程序执行完毕")

要点:改放 try 里一起 commit(原子性)、查放 try 外、最后别忘 close()

🤔 再想一步(选做)
上面的密码、host 都写死在代码里,换台电脑就得改好几处。试着把这 4 个连接参数抽成开头的几个变量,让程序更好维护。行有余力的同学,可以查一下"参数化查询"——把用户输入直接拼进 SQL 字符串是有安全隐患的,参数化能避免它。

完成检查

勾一勾,看看自己走到哪了

完成进度:0 / 6

🎉 做完前 4 个任务,本章核心你就全拿下了

回顾今天真正动手做出来的:5 步连上库、带 try-except 的增 / 改、commit 的作用、用 fetch 把查询打印出来。这几样,就是"用 Python 操作数据库"的全部要点。整门课到这里也圆满了 👏。