9-数据库操作
约 6342 字大约 21 分钟
2026-05-22
在前面的章节中,已经介绍了Python编程的基础知识,包括变量、数据类型、选择结构、循环结构、函数、列表、字典、元组、面向对象编程、文件操作和模块等内容。能够编写程序来处理各种数据,但是有一个问题:程序运行结束后,数据就消失了。比如编写了一个学生成绩管理程序,运行时可以录入成绩、查询成绩,但是一旦关闭程序,所有录入的成绩数据就全部丢失了,下次运行还得重新录入。这显然不是想要的结果。
要解决这个问题,就需要把数据"永久保存"起来,这就是"数据持久化"的思想。在第八章学习了文件操作,可以把数据保存到文本文件中,这是一种简单的数据持久化方式。但是当数据量很大、数据之间的关系比较复杂时,文件操作就显得力不从心了。比如,一个学校有几万名学生的信息,还要记录每个学生选了哪些课程、每门课程的成绩是多少,如果用文件来管理这些数据,查找和修改都会非常困难。
数据库技术就是为解决大规模数据存储和管理问题而诞生的。数据库就像一个超级"文件柜",可以高效地存储、组织、查询和管理大量数据。MySQL是目前最流行的开源关系型数据库之一,而Python通过pymysql模块可以方便地连接和操作MySQL数据库。本章将介绍数据库的基本概念,学习如何安装和配置MySQL,掌握使用Python操作MySQL数据库的方法,最终能够独立开发一个完整的数据库应用程序。
【学习目标】
知识目标
理解数据库、数据库管理系统、关系型数据库等基本概念。
了解MySQL数据库的安装、配置和基本操作方法。
掌握pymysql模块的安装和使用方法。
掌握SQL语言的基本语法,包括CREATE、INSERT、SELECT、UPDATE、DELETE等语句。
能力目标
能够使用Python连接MySQL数据库,完成基本的数据库操作。
能够设计简单的数据库表结构,并使用SQL语句进行数据的增删改查。
能够结合列表、字典等数据结构,处理数据库查询结果。
能够开发基于数据库的简单信息管理系统。
素养目标
培养数据安全意识和信息保密意识,养成良好的数据管理习惯。
树立依法依规使用数据的观念,尊重数据隐私和知识产权。
培养严谨细致的工作作风,注重数据操作的准确性和安全性。
1.MySQL数据库概述
1.1 什么是数据库
在日常生活中,会和各种各样的数据打交道。去超市购物,收银台会扫描商品条码、计算总价、打印小票;去图书馆借书,管理员会查询你的借阅记录、办理借还手续;在学校里,教务系统会记录每个学生的选课信息、考试成绩。这些场景背后,都需要一个系统来高效地存储和管理大量的数据,这个系统就是数据库。
数据库(Database,简称DB)是按照一定的数据模型组织、存储和管理数据的仓库。简单来说,数据库就像一个有组织的"电子文件柜",它把相关的数据按照一定的规则存放在一起,方便随时查找、添加、修改和删除。与普通的文件相比,数据库有以下几个显著的优势:
第一,存储容量大。一个文本文件通常只能存储几千到几万条数据,而数据库可以轻松存储数百万甚至数十亿条数据。比如,淘宝网每天要处理数十亿条交易数据,这些数据都存储在数据库中。
第二,查询速度快。如果要在文件中查找某个特定数据,可能需要从头到尾遍历整个文件,效率很低。而数据库使用了索引等技术,可以在海量数据中快速定位到目标数据,查询速度非常快。
第三,支持并发访问。文件一般一次只能被一个程序读写,而数据库允许多个用户同时访问和操作数据。比如,多个收银员可以同时使用同一个商品数据库进行结账操作,互不影响。
第四,数据安全性高。数据库提供了用户权限管理、数据备份、事务处理等安全机制,可以有效保护数据不被丢失或篡改。而文件一旦被误删或损坏,恢复起来非常困难。
数据库管理系统(Database Management System,简称DBMS)是管理数据库的软件系统,它提供了创建、查询、更新、删除数据等功能。常见的数据库管理系统有MySQL、Oracle、SQL Server、SQLite等。本书选择MySQL作为教学数据库,因为它是免费开源的、功能强大、使用广泛,非常适合初学者学习。
1.2 认识MySQL
MySQL是全球最流行的开源关系型数据库管理系统之一。它最早由瑞典MySQL AB公司开发,目前属于Oracle公司旗下产品。MySQL以其体积小、速度快、总体拥有成本低等特点,被广泛应用于各类Web应用程序中,包括淘宝、百度、新浪等知名网站都在使用MySQL。
所谓"关系型数据库",是指数据以表格(Table)的形式组织存储,表格之间可以建立关联关系。就像日常使用的Excel表格一样,数据按照行和列排列。比如,一个学生信息表可能包含学号、姓名、性别、年龄、专业等列,每一行代表一个学生的信息。关系型数据库的核心概念包括以下几个:
数据库(Database):数据的容器,一个数据库管理系统可以管理多个数据库。比如,一个学校可以创建一个"学生管理系统"数据库,里面包含学生表、课程表、成绩表等。
数据表(Table):数据的组织形式,由行(Row)和列(Column)组成。每一行称为一条"记录",每一列称为一个"字段"。比如,学生表的每一行是一个学生的完整信息,每一列是学生的某个属性(如姓名、年龄等)。
主键(Primary Key):唯一标识表中每一行记录的字段。比如,学生表中的"学号"字段可以作为主键,因为每个学生的学号都是唯一的,不会重复。主键的作用就像身份证号一样,通过它可以准确地找到某一条特定的记录。
外键(Foreign Key):用于建立表与表之间关联关系的字段。比如,成绩表中可以包含一个"学号"字段作为外键,指向学生表中的"学号"主键,这样就可以通过成绩表找到对应的学生信息。
1.3 安装与配置MySQL
要使用MySQL数据库,首先需要在电脑上安装MySQL软件。MySQL的安装过程比较简单,下面以Windows系统为例,介绍MySQL的安装步骤。
第一步,下载MySQL安装包。打开MySQL官方网站(https://dev.mysql.com/downloads/),选择"MySQL Installer for Windows"。建议下载MySQL 8.0版本,这是目前最稳定的版本。
第二步,运行安装程序。双击下载的安装包,按照安装向导的提示一步步操作。在安装过程中,安装向导会要求设置root用户的密码,这个密码非常重要,请务必记住。root用户是MySQL的最高权限用户,类似于Windows系统的Administrator账户。建议设置一个简单易记的密码,方便后续学习使用。
第三步,配置环境变量。安装完成后,需要将MySQL的bin目录添加到系统的环境变量PATH中,这样就可以在命令行窗口中直接使用mysql命令。具体方法是:右键点击"此电脑"→"属性"→"高级系统设置"→"环境变量",在"系统变量"中找到Path,点击"编辑",添加MySQL的bin目录路径(如C:\Program Files\MySQL\MySQL Server 8.0\bin),如图9-1环境变量设置。

图9-1环境变量设置
第四步,验证安装。打开命令行窗口(按Win+R,输入cmd,回车),输入以下命令:
代码 9-1:验证MySQL安装
mysql --version如果安装成功,会显示MySQL的版本号信息。然后输入以下命令登录MySQL:
mysql -u root -p系统会提示你输入密码,输入安装时设置的root密码后,如果看到"mysql>"提示符,说明已经成功登录MySQL数据库。此时可以输入"exit"退出MySQL。如图9-2数据库MySQL安装验证。

图9-2数据库MySQL安装验证
1.4 MySQL基本操作
MySQL提供了两种操作方式:命令行方式和图形化工具方式。命令行方式需要输入SQL语句来操作数据库,适合有一定基础的用户;图形化工具方式通过可视化界面操作数据库,更加直观方便,适合初学者。本节介绍使用图形化工具Navicat来操作MySQL数据库。
Navicat是一款流行的数据库管理工具,提供了直观的图形界面,可以方便地创建数据库、创建表、插入数据、查询数据等。Navicat有免费的教育版,可以在官网申请使用。安装Navicat后,按照以下步骤操作:
第一步,新建连接。打开Navicat,点击左上角的"连接"按钮,选择"MySQL",在弹出的对话框中输入连接信息:连接名可以随意填写(如"本地MySQL"),主机名填写"localhost"(表示本机),端口填写"3306"(MySQL默认端口),用户名填写"root",密码填写安装时设置的root密码。点击"测试连接",如果提示连接成功,点击"确定"保存连接。如图9-3用Navicat连接数据库。

图9-3用Navicat连接数据库
第二步,创建数据库。在左侧的连接列表中双击刚才创建的连接,展开后可以看到已有的数据库列表。右键点击"本地MySQL",选择"新建数据库",在弹出的对话框中输入数据库名称(如"student_db"),字符集选择"utf8mb4",排序规则选择"utf8mb4_general_ci",点击"确定"完成创建。如图9-4用Navicat创建数据库。

图9-4用Navicat创建数据库
第三步,创建数据表。双击打开刚创建的"student_db"数据库,点击上方的"新建表"按钮,开始设计表结构。在表设计器中,可以添加字段、设置字段名、数据类型、是否为主键等。比如,创建一个学生表(students)。
表 9-1 学生表(students)结构设计
| 字段名 | 数据类型 | 说明 | 约束 | | id | INT | 学号 | 主键,自动增长 | | name | VARCHAR(50) | 姓名 | 不能为空 | | gender | VARCHAR(10) | 性别 | 无 | | age | INT | 年龄 | 无 | | major | VARCHAR(50) | 专业 | 无 | 设置好字段后,点击"保存",输入表名"students",完成表的创建,如图9-5用Navicat创建表。接下来,可以双击打开students表,直接在表格中输入数据,就像使用Excel一样方便。

图9-5用Navicat创建表
2.MySQL数据库连接
2.1 安装pymysql模块
Python本身不能直接操作MySQL数据库,需要通过专门的"驱动模块"来与数据库通信。pymysql就是这样一个驱动模块,它是纯Python实现的MySQL客户端库,安装简单、使用方便,非常适合教学和学习使用。安装pymysql模块的方法和安装其他第三方模块一样,在命令行窗口中输入以下命令:
代码 9-2:安装pymysql模块
pip install pymysql安装过程中,命令行会显示下载进度和安装信息。安装完成后,可以通过以下命令验证是否安装成功:
代码 9-3:验证pymysql安装
import pymysql
print(pymysql.__version__)如果没有报错并且打印出了版本号,说明pymysql已经安装成功。如果提示"ModuleNotFoundError:No module named'pymysql'",说明安装失败,请检查网络连接或尝试使用国内镜像源安装:pip install pymysql -i https://pypi.tuna.tsinghua.edu.cn/simple。
2.2 建立数据库连接
安装好pymysql模块后,就可以在Python程序中连接MySQL数据库了。连接数据库需要提供以下信息:数据库主机地址(host)、端口号(port)、用户名(user)、密码(password)和数据库名称(database)。下面是建立数据库连接的完整代码:
代码 9-4:建立数据库连接
import pymysql
# 建立数据库连接
conn = pymysql.connect(
host="localhost", # 数据库主机地址
port=3306, # 端口号
user="root", # 用户名
password="123456", # 密码
database="student_db" # 数据库名称
)
print("数据库连接成功!")
# 关闭连接
conn.close()
print("数据库连接已关闭。")运行结果如图9-6用pymysql连接数据库。

图9-6用pymysql连接数据库
如果输出"数据库连接成功!",说明Python已经成功连接到了MySQL数据库。pymysql.connect()函数的各个参数说明如下:host参数指定数据库服务器的地址,如果是本机数据库则填写"localhost";port参数指定端口号,MySQL默认端口是3306;user参数指定登录数据库的用户名;password参数指定登录密码;database参数指定要连接的数据库名称。
在实际开发中,通常会将数据库连接信息集中管理,方便维护和修改。可以把这些信息存储在一个字典中,然后通过字典来传递参数。
代码 9-5:使用字典管理数据库连接配置
import pymysql
# 数据库连接配置(使用字典存储)
db_config = {
"host": "localhost",
"port": 3306,
"user": "root",
"password": "123456",
"database": "student_db"
}
# 使用 ** 解包字典作为连接参数
conn = pymysql.connect(**db_config)
print("数据库连接成功!")
conn.close()这里用到了字典来存储数据库连接配置,使用时通过"**"运算符将字典解包为关键字参数传递给connect()函数。这样做的好处是,当需要修改连接信息时,只需要修改字典中的值即可,不需要改动连接代码。
2.3 关闭数据库连接
数据库连接是一种宝贵的资源,每次连接都会占用数据库服务器的内存和连接数。如果程序中打开了数据库连接却不关闭,会导致资源浪费,严重时甚至会使数据库服务器因为连接数过多而无法响应。因此,使用完数据库后,一定要及时关闭连接。
关闭连接的方法很简单,调用连接对象的close()方法即可。但是,在实际编程中,经常会遇到这样的情况:在操作数据库的过程中发生了异常(比如SQL语句写错了),程序直接崩溃退出,close()方法根本没有被执行到,连接就没有被关闭。为了解决这个问题,Python提供了with语句来自动管理资源的释放:
代码 9-6:使用with语句自动管理数据库连接
import pymysql
# 使用 with 语句自动管理连接
db_config = {
"host": "localhost",
"port": 3306,
"user": "root",
"password": "123456",
"database": "student_db"
}
try:
with pymysql.connect(**db_config) as conn:
print("数据库连接成功!")
# 在这里进行数据库操作...
print("数据库操作完成。")
# with 块结束后,连接会自动关闭
print("连接已自动关闭。")
except Exception as e:
print("数据库操作出错:", e)使用with语句后,无论数据库操作是否成功,无论是否发生异常,连接都会在with代码块结束后自动关闭。这种方式更加安全可靠,是推荐的做法。同时,还使用了try...except语句来捕获可能出现的异常,避免程序因为数据库错误而崩溃。
3.MySQL数据库读写
连接上数据库之后,就可以对数据库进行各种操作了。数据库的基本操作可以概括为四个字——"增删改查",英文缩写为CRUD(Create、Read、Update、Delete)。本节将详细介绍如何使用Python和SQL语句来完成这四种操作。
3.1 创建数据库和表
在进行数据操作之前,首先需要确保数据库和表已经创建好。虽然可以使用Navicat等图形化工具来创建,但也可以使用Python代码来创建,这样更加灵活,也更便于程序的自动化部署。创建数据库和表需要使用SQL(Structured Query Language,结构化查询语言)语句。SQL是操作关系型数据库的标准语言,几乎所有的关系型数据库都支持SQL。
下面是使用Python创建数据库和表的代码:
代码 9-7:创建数据库和表
import pymysql
# 先连接MySQL服务器(不指定数据库)
conn = pymysql.connect(
host="localhost",
port=3306,
user="root",
password="123456"
)
cursor = conn.cursor()
# 创建数据库(如果不存在)
cursor.execute("CREATE DATABASE IF NOT EXISTS student_db CHARACTER SET utf8mb4")
print("数据库创建成功!")
# 切换到该数据库
cursor.execute("USE student_db")
# 创建学生表
create_table_sql = """
CREATE TABLE IF NOT EXISTS students (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
gender VARCHAR(10),
age INT,
major VARCHAR(50)
) CHARACTER SET utf8mb4
"""
cursor.execute(create_table_sql)
print("学生表创建成功!")
cursor.close()
conn.close()这段代码中有几个重要的知识点需要理解。首先,cursor(游标)是数据库操作的核心对象,所有的SQL语句都需要通过游标来执行。可以把游标理解为一个"指挥棒",通过它向数据库发送指令。创建游标的方法是调用连接对象的cursor()方法。
其次,执行SQL语句使用的是游标的execute()方法。注意,CREATE DATABASE和CREATE TABLE语句只需要执行一次,如果数据库或表已经存在,使用"IF NOT EXISTS"关键字可以避免重复创建导致的错误。
最后,"AUTO_INCREMENT"关键字表示该字段是自动增长的,每次插入新记录时不需要手动指定id的值,数据库会自动为其分配一个递增的编号。"PRIMARY KEY"关键字表示该字段是主键。"NOT NULL"关键字表示该字段的值不能为空。"VARCHAR(50)"表示该字段是可变长度字符串,最大长度为50个字符。
3.2 插入数据
表创建好之后,就可以向表中插入数据了。插入数据使用SQL的INSERT语句。下面是插入单条数据和批量插入多条数据的代码示例:
代码 9-8:插入数据
import pymysql
db_config = {
"host": "localhost",
"port": 3306,
"user": "root",
"password": "123456",
"database": "student_db"
}
conn = pymysql.connect(**db_config)
cursor = conn.cursor()
# ---- 插入单条数据 ----
insert_sql = "INSERT INTO students (name, gender, age, major) VALUES (%s, %s, %s, %s)"
cursor.execute(insert_sql, ("张三", "男", 19, "计算机科学"))
conn.commit() # 提交事务
print("插入成功:张三")
# ---- 插入多条数据(使用元组列表) ----
students_data = [
("李四", "女", 20, "软件工程"),
("王五", "男", 18, "人工智能"),
("赵六", "女", 19, "数据科学"),
("钱七", "男", 20, "计算机科学"),
("孙八", "女", 19, "软件工程")
]
cursor.executemany(insert_sql, students_data)
conn.commit()
print("批量插入成功,共", cursor.rowcount, "条")
cursor.close()
conn.close()这段代码中有两个非常重要的知识点。第一,SQL语句中的"%s"是参数占位符,不是字符串格式化。使用参数占位符可以防止SQL注入攻击,这是一种常见的安全漏洞。千万不要使用字符串拼接的方式来构造SQL语句,比如"INSERT INTO students VALUES ('" + name + "', ...)",这样做非常不安全。
第二,conn.commit()方法用于提交事务。在MySQL中,对数据的修改操作(插入、更新、删除)默认不会立即生效,而是需要手动提交事务。这就好比编辑一个文档,修改的内容不会自动保存,需要点击"保存"按钮才会写入磁盘。如果忘记提交事务,数据修改将不会生效。
第三,executemany()方法可以一次性执行多条INSERT语句,比循环调用execute()效率更高。注意,传入的参数是一个包含多个元组的列表,每个元组代表一条记录的数据。
3.3 查询数据
查询数据是数据库操作中最常用的功能。查询数据使用SQL的SELECT语句。查询结果通过游标获取,可以使用fetchone()获取一条记录、fetchall()获取所有记录、fetchmany(n)获取n条记录。下面是查询数据的代码示例:
代码 9-9:查询数据
import pymysql
db_config = {
"host": "localhost",
"port": 3306,
"user": "root",
"password": "123456",
"database": "student_db"
}
conn = pymysql.connect(**db_config)
cursor = conn.cursor()
# ---- 查询所有数据 ----
cursor.execute("SELECT * FROM students")
results = cursor.fetchall()
print("共查询到", len(results), "条记录")
print("学号\t姓名\t性别\t年龄\t专业")
for row in results:
print(row[0], "\t", row[1], "\t", row[2], "\t",row[3], "\t", row[4])
# ---- 条件查询 ----
cursor.execute("SELECT * FROM students WHERE major = %s",("计算机科学",))
results = cursor.fetchall()
print("\n计算机科学专业的学生:")
for row in results:
print(row[1], "-", row[4])
cursor.close()
conn.close()fetchall()方法返回的是一个包含元组的列表,每个元组代表一条记录。比如,results可能是这样的结构:[(1,'张三', '男', 19, '计算机科学'), (2, '李四', '女', 20,'软件工程'),...]。可以通过索引来访问每个字段的值,比如row[0]是学号,row[1]是姓名,以此类推。
但是,通过索引访问字段值不够直观,容易出错(比如记不清第几个字段是姓名)。更好的做法是使用DictCursor(字典游标),它返回的每条记录是一个字典,可以通过字段名来访问值:
代码 9-10:使用字典游标查询数据
import pymysql
conn = pymysql.connect(
host="localhost",
port=3306,
user="root",
password="123456",
database="student_db"
)
# 创建字典游标
cursor = conn.cursor(pymysql.cursors.DictCursor)
cursor.execute("SELECT * FROM students")
results = cursor.fetchall()
print("使用字典游标查询结果:")
for row in results:
print("姓名:" + row["name"]
+ ",性别:" + row["gender"]
+ ",专业:" + row["major"])
cursor.close()
conn.close()使用字典游标后,每条记录变成了一个字典,比如{"id": 1, "name":"张三", "gender": "男", "age": 19, "major":"计算机科学"}。通过row["name"]来访问姓名字段,代码更加清晰易读,也不容易出错。在实际开发中,推荐使用字典游标。
3.4 更新数据
更新数据使用SQL的UPDATE语句。更新操作可以修改表中已有记录的字段值。下面是更新数据的代码示例:
代码 9-11:更新数据
import pymysql
conn = pymysql.connect(
host="localhost",
port=3306,
user="root",
password="123456",
database="student_db"
)
cursor = conn.cursor()
# ---- 更新单条数据 ----
# 将张三的年龄更新为20岁
update_sql = "UPDATE students SET age = %s WHERE name = %s"
cursor.execute(update_sql, (20, "张三"))
conn.commit()
print("更新成功,影响", cursor.rowcount, "行")
# ---- 批量更新数据 ----
# 将所有软件工程专业学生的年龄加1
cursor.execute(
"UPDATE students SET age = age + 1 WHERE major = %s",
("软件工程",)
)
conn.commit()
print("批量更新成功,影响", cursor.rowcount, "行")
cursor.close()
conn.close()UPDATE语句的语法是"UPDATE 表名 SET 字段名 = 新值 WHERE条件"。其中,WHERE子句用于指定要更新的记录,如果不加WHERE子句,将会更新表中的所有记录。cursor.rowcount属性返回受影响的行数,可以用来判断更新操作是否成功。
3.5 删除数据
删除数据使用SQL的DELETE语句。删除操作会从表中移除符合条件的记录。下面是删除数据的代码示例:
代码 9-12:删除数据
import pymysql
conn = pymysql.connect(
host="localhost",
port=3306,
user="root",
password="123456",
database="student_db"
)
cursor = conn.cursor()
# ---- 删除单条数据 ----
# 删除名字为"钱七"的学生
delete_sql = "DELETE FROM students WHERE name = %s"
cursor.execute(delete_sql, ("钱七",))
conn.commit()
print("删除成功,影响", cursor.rowcount, "行")
# ---- 删除满足条件的所有数据 ----
# 删除年龄小于19岁的学生
cursor.execute(
"DELETE FROM students WHERE age < %s",
(19,)
)
conn.commit()
print("批量删除成功,影响", cursor.rowcount, "行")
cursor.close()
conn.close()DELETE语句的语法是"DELETE FROM 表名 WHERE条件"。同样,WHERE子句非常重要,如果不加WHERE子句,将会删除表中的所有数据,这是一个非常危险的操作!在实际开发中,执行删除操作前最好先查询确认一下要删除的数据,避免误删。常用SQL语句如表9-2.
表 9-2 SQL常用语句一览
| 操作 | SQL语句 | 说明 | | 创建表 | CREATE TABLE 表名 (字段定义...) | 定义表结构 | | 插入数据 | INSERT INTO 表名 (字段) VALUES (值) | 添加新记录 | | 查询数据 | SELECT 字段 FROM 表名 WHERE 条件 | 检索记录 | | 更新数据 | UPDATE 表名 SET 字段=值 WHERE 条件 | 修改记录 | | 删除数据 | DELETE FROM 表名 WHERE 条件 | 删除记录 |
