第 03 章 Python 操作 MySQL 数据库实战全解

一、章节学习目标

本章聚焦 Python 与 MySQL 数据库的交互核心技术,通过系统化讲解,帮助开发者掌握从环境搭建到复杂数据操作的全流程。学习完成后,你将达成以下目标:

  1. 熟练安装并配置 Python 操作 MySQL 的核心驱动库,理解不同驱动的适用场景。
  2. 掌握 Python 与 MySQL 数据库的连接、断开及异常处理机制,保障数据库操作的稳定性。
  3. 精通数据表的创建、删除等基础管理操作,能够通过 Python 代码完成数据库结构的动态维护。
  4. 熟练运用INSERTUPDATEDELETESELECT四大核心 SQL 语句,实现数据的增删改查。
  5. 掌握事务管理、连接池配置等高级特性,提升数据库操作的安全性与性能。
  6. 能够处理数据库操作中的常见异常,编写健壮、可维护的 Python 数据库操作代码。

二、前置准备:安装 Python MySQL 连接库

Python 与 MySQL 数据库的交互依赖于第三方驱动库,目前主流的有mysql-connector-python(MySQL 官方驱动)和PyMySQL(纯 Python 轻量级驱动),二者核心特性与安装方式如下表所示:

表格

驱动库名称 核心特性 安装命令 适用场景
mysql-connector-python 1. MySQL 官方开发维护,文档完善、持续更新2. 纯 Python 实现,无需依赖外部 C 库3. 支持 SSL 加密、预处理语句、事务控制4. 符合 DB-API 2.0 规范,兼容性强 pip install mysql-connector-python 企业级应用、需要与 MySQL 官方特性深度集成、对兼容性要求高的项目
PyMySQL 1. 纯 Python 编写,轻量级、安装便捷2. 社区活跃,性能表现优异3. 语法简洁,上手成本低 pip install pymysql 中小型项目、脚本自动化、快速开发原型、追求轻量级依赖的场景

2.1 安装验证

安装完成后,可通过以下 Python 代码验证驱动是否安装成功:

python

运行

复制代码
# 验证mysql-connector-python
try:
    import mysql.connector
    print(f"mysql-connector-python版本:{mysql.connector.__version__}")
    print("✅ 安装成功!")
except ImportError:
    print("❌ 未安装mysql-connector-python,请执行pip安装命令")

# 验证PyMySQL
try:
    import pymysql
    print(f"PyMySQL版本:{pymysql.__version__}")
    print("✅ 安装成功!")
except ImportError:
    print("❌ 未安装PyMySQL,请执行pip安装命令")

三、Python 连接 MySQL 数据库

连接 MySQL 是数据库操作的基础,核心包括连接配置、建立连接、游标创建、异常处理和连接关闭五个步骤,以下以mysql-connector-python为例详细讲解。

3.1 连接参数详解

建立连接时需配置核心参数,各参数含义及取值建议如下表:

表格

参数名 含义 取值建议 必选
host 数据库服务器地址 本地填localhost127.0.0.1;远程填服务器 IP / 域名
port 数据库端口号 MySQL 默认端口为3306,若修改过需对应填写
database 目标数据库名 需提前在 MySQL 中创建的数据库名称
user 数据库用户名 生产环境建议使用专用账号,避免使用 root
password 数据库密码 对应用户名的登录密码,生产环境禁止硬编码
charset 字符集 推荐utf8mb4(支持 emoji,兼容所有 Unicode 字符)
autocommit 自动提交模式 False(手动控制事务,推荐);True(自动提交,适合简单查询)
ssl_ca/ssl_cert/ssl_key SSL 加密配置 远程连接需加密时,填写 SSL 证书路径

3.2 基础连接代码(mysql-connector-python)

python

运行

复制代码
import mysql.connector
from mysql.connector import Error

# 数据库连接配置
db_config = {
    "host": "localhost",
    "port": 3306,
    "database": "test_db",  # 需提前在MySQL中创建
    "user": "root",
    "password": "your_password",
    "charset": "utf8mb4",
    "autocommit": False
}

# 全局变量存储连接和游标
conn = None
cursor = None

try:
    # 1. 建立数据库连接
    conn = mysql.connector.connect(**db_config)
    
    if conn.is_connected():
        # 2. 获取MySQL服务器版本信息
        db_version = conn.get_server_info()
        print(f"✅ 成功连接MySQL服务器,版本:{db_version}")
        
        # 3. 创建游标对象(用于执行SQL语句)
        cursor = conn.cursor()
        
        # 4. 执行基础查询,查看当前数据库
        cursor.execute("SELECT DATABASE();")
        current_db = cursor.fetchone()[0]
        print(f"📌 当前操作数据库:{current_db}")

except Error as e:
    # 异常处理:打印错误信息
    print(f"❌ 数据库操作异常:{e}")
    # 发生异常时回滚事务(若连接已建立)
    if conn:
        conn.rollback()

finally:
    # 5. 关闭游标和连接,释放资源
    if cursor:
        cursor.close()
    if conn and conn.is_connected():
        conn.close()
        print("🔌 数据库连接已关闭")

3.3 连接优化与异常处理

3.3.1 上下文管理器(with 语句)

使用with语句可自动管理资源,无需手动关闭连接和游标,代码更简洁、更安全:

python

运行

复制代码
import mysql.connector
from mysql.connector import Error

db_config = {
    "host": "localhost",
    "database": "test_db",
    "user": "root",
    "password": "your_password",
    "charset": "utf8mb4"
}

try:
    # with语句自动管理连接和游标
    with mysql.connector.connect(**db_config) as conn:
        with conn.cursor() as cursor:
            # 执行SQL语句
            cursor.execute("SELECT VERSION();")
            version = cursor.fetchone()
            print(f"MySQL版本:{version[0]}")
            
            # 提交事务(非查询操作需手动提交)
            conn.commit()

except Error as e:
    print(f"❌ 异常:{e}")
3.3.2 常见连接异常排查

表格

异常码 异常原因 解决方法
1045 用户名 / 密码错误 检查userpassword配置,确认账号密码正确
2003 无法连接到主机 检查host是否正确,确认 MySQL 服务已启动、端口未被占用
1049 数据库不存在 提前在 MySQL 中创建目标数据库,或检查database配置
2059 认证方式不兼容 MySQL8.0 + 使用caching_sha2_password认证,需修改用户认证方式或安装对应驱动版本

四、数据表基础操作

通过 Python 代码可实现数据表的创建、删除、查看等管理操作,以下为核心操作详解。

4.1 创建数据表

创建数据表时需定义表名、字段名、数据类型、约束条件(主键、非空、唯一等),示例代码如下:

python

运行

复制代码
import mysql.connector
from mysql.connector import Error

# 连接配置
db_config = {
    "host": "localhost",
    "database": "test_db",
    "user": "root",
    "password": "your_password",
    "charset": "utf8mb4"
}

# 建表SQL语句(员工表)
create_table_sql = """
CREATE TABLE IF NOT EXISTS employees (
    id INT AUTO_INCREMENT PRIMARY KEY COMMENT '员工ID,自增主键',
    name VARCHAR(50) NOT NULL COMMENT '员工姓名',
    age TINYINT UNSIGNED COMMENT '员工年龄',
    department VARCHAR(100) NOT NULL COMMENT '所属部门',
    salary DECIMAL(10, 2) NOT NULL COMMENT '薪资',
    hire_date DATE NOT NULL COMMENT '入职日期',
    email VARCHAR(100) UNIQUE COMMENT '邮箱,唯一',
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='员工信息表';
"""

try:
    with mysql.connector.connect(**db_config) as conn:
        with conn.cursor() as cursor:
            # 执行建表语句
            cursor.execute(create_table_sql)
            print("✅ 数据表employees创建成功(若已存在则跳过)")
            
            # 查看表结构
            cursor.execute("DESC employees;")
            table_structure = cursor.fetchall()
            print("\n📋 表结构信息:")
            for field in table_structure:
                print(f"字段名:{field[0]}, 类型:{field[1]}, 约束:{field[2]}")

except Error as e:
    print(f"❌ 建表异常:{e}")

4.2 数据表删除

删除数据表需谨慎操作,数据删除后不可恢复,示例代码:

python

运行

复制代码
# 删表SQL语句
drop_table_sql = "DROP TABLE IF EXISTS employees;"

try:
    with mysql.connector.connect(**db_config) as conn:
        with conn.cursor() as cursor:
            cursor.execute(drop_table_sql)
            print("✅ 数据表employees已删除(若存在)")
except Error as e:
    print(f"❌ 删表异常:{e}")

4.3 数据表查看

查看数据库中所有数据表,代码如下:

python

运行

复制代码
# 查看表SQL语句
show_tables_sql = "SHOW TABLES;"

try:
    with mysql.connector.connect(**db_config) as conn:
        with conn.cursor() as cursor:
            cursor.execute(show_tables_sql)
            tables = cursor.fetchall()
            print(f"\n📌 数据库{db_config['database']}中的数据表:")
            for table in tables:
                print(f"- {table[0]}")
except Error as e:
    print(f"❌ 查看表异常:{e}")

五、核心数据操作(CRUD)

CRUD 是数据库操作的核心,包括数据插入(Create)、查询(Read)、更新(Update)、删除(Delete),以下结合employees表详细讲解各操作。

5.1 数据插入(INSERT)

数据插入分为单条插入和批量插入,推荐使用参数化查询(%s占位符),避免 SQL 注入攻击。

5.1.1 单条插入

python

运行

复制代码
import mysql.connector
from mysql.connector import Error

db_config = {
    "host": "localhost",
    "database": "test_db",
    "user": "root",
    "password": "your_password",
    "charset": "utf8mb4"
}

# 单条插入SQL
insert_single_sql = """
INSERT INTO employees (name, age, department, salary, hire_date, email)
VALUES (%s, %s, %s, %s, %s, %s);
"""

# 插入数据
employee_data = ("张三", 28, "技术部", 15000.00, "2023-01-15", "zhangsan@example.com")

try:
    with mysql.connector.connect(**db_config) as conn:
        with conn.cursor() as cursor:
            # 执行插入
            cursor.execute(insert_single_sql, employee_data)
            # 提交事务(非查询操作必须提交)
            conn.commit()
            # 获取自增主键ID
            new_id = cursor.lastrowid
            print(f"✅ 单条插入成功,新增员工ID:{new_id}")
            print(f"📌 受影响行数:{cursor.rowcount}")
except Error as e:
    # 异常时回滚
    conn.rollback()
    print(f"❌ 单条插入异常:{e}")
5.1.2 批量插入

批量插入使用executemany()方法,效率远高于多次单条插入,适合大量数据导入:

python

运行

复制代码
# 批量插入SQL(复用单条插入语句)
insert_batch_sql = """
INSERT INTO employees (name, age, department, salary, hire_date, email)
VALUES (%s, %s, %s, %s, %s, %s);
"""

# 批量数据
batch_employee_data = [
    ("李四", 30, "销售部", 12000.00, "2023-02-20", "lisi@example.com"),
    ("王五", 25, "人事部", 9000.00, "2023-03-10", "wangwu@example.com"),
    ("赵六", 35, "财务部", 18000.00, "2023-01-05", "zhaoliu@example.com")
]

try:
    with mysql.connector.connect(**db_config) as conn:
        with conn.cursor() as cursor:
            # 批量插入
            cursor.executemany(insert_batch_sql, batch_employee_data)
            conn.commit()
            print(f"✅ 批量插入成功,新增{cursor.rowcount}条数据")
except Error as e:
    conn.rollback()
    print(f"❌ 批量插入异常:{e}")

5.2 数据查询(SELECT)

数据查询是最常用的操作,支持单条查询、多条查询、条件查询、模糊查询等,可通过fetchone()fetchall()fetchmany()获取结果。

5.2.1 基础查询

python

运行

复制代码
# 查询所有员工数据
query_all_sql = "SELECT * FROM employees;"

try:
    with mysql.connector.connect(**db_config) as conn:
        with conn.cursor() as cursor:
            # 执行查询
            cursor.execute(query_all_sql)
            # 获取所有结果
            all_employees = cursor.fetchall()
            print(f"\n📋 共查询到{len(all_employees)}条员工数据:")
            # 遍历结果
            for emp in all_employees:
                print(f"ID:{emp[0]}, 姓名:{emp[1]}, 部门:{emp[3]}, 薪资:{emp[4]}")
except Error as e:
    print(f"❌ 查询异常:{e}")
5.2.2 条件查询

python

运行

复制代码
# 按部门查询员工(条件查询)
query_dept_sql = "SELECT name, salary, hire_date FROM employees WHERE department = %s;"
dept_name = "技术部"

try:
    with mysql.connector.connect(**db_config) as conn:
        with conn.cursor() as cursor:
            cursor.execute(query_dept_sql, (dept_name,))
            # 获取单条结果(若存在)
            tech_emp = cursor.fetchone()
            if tech_emp:
                print(f"\n📌 技术部员工:姓名={tech_emp[0]}, 薪资={tech_emp[1]}, 入职日期={tech_emp[2]}")
            else:
                print("📌 技术部无员工数据")
except Error as e:
    print(f"❌ 条件查询异常:{e}")
5.2.3 分页查询

python

运行

复制代码
# 分页查询(每页2条,第1页)
page_query_sql = "SELECT * FROM employees LIMIT %s OFFSET %s;"
page_size = 2
page_num = 1
offset = (page_num - 1) * page_size

try:
    with mysql.connector.connect(**db_config) as conn:
        with conn.cursor() as cursor:
            cursor.execute(page_query_sql, (page_size, offset))
            page_employees = cursor.fetchall()
            print(f"\n📋 第{page_num}页数据(每页{page_size}条):")
            for emp in page_employees:
                print(f"ID:{emp[0]}, 姓名:{emp[1]}")
except Error as e:
    print(f"❌ 分页查询异常:{e}")
5.2.4 模糊查询

python

运行

复制代码
# 模糊查询(姓名包含"张"的员工)
fuzzy_query_sql = "SELECT name, department FROM employees WHERE name LIKE %s;"
search_key = "%张%"

try:
    with mysql.connector.connect(**db_config) as conn:
        with conn.cursor() as cursor:
            cursor.execute(fuzzy_query_sql, (search_key,))
            fuzzy_emps = cursor.fetchall()
            print(f"\n📋 姓名包含"张"的员工:")
            for emp in fuzzy_emps:
                print(f"姓名:{emp[0]},
相关推荐
SPC的存折2 小时前
1、MySQL故障排查与运维案例
linux·运维·服务器·数据库·mysql
小臭希2 小时前
Redis(NoSQL数据库,Linux-Ubuntu环境下)
数据库·redis·缓存
cdcdhj2 小时前
在window下将Mongodb单机改为副本集,只用于测试环境,实际上并没有增加真的副本集
数据库·mongodb
悟空码字2 小时前
MySQL性能优化的天花板:10条你必须掌握的顶级SQL分析技巧
java·后端·mysql
xcjbqd02 小时前
如何修改Oracle服务器默认的日期格式_NLS_DATE_FORMAT全局配置
jvm·数据库·python
HealthScience2 小时前
SpliceVarDB数据集说明
数据库·oracle
倔强的石头_2 小时前
表空间自动目录创建与存储管理实践:参数化配置与性能优化
数据库
white-persist2 小时前
【vulhub spring CVE-2018-1270】CVE-2018-1270 Spring Messaging 远程命令执行漏洞 完整复现详细分析解释
java·服务器·网络·数据库·后端·python·spring
EnCi Zheng2 小时前
P2G-Python字符串方法完全指南-split、join、strip、replace的Python编程利器
开发语言·python