Python连接MySQL执行SQL查询的完整代码示例

Luna
Luna
发布时间:2026-11-04| 3人浏览过
原创

详细讲解在Python中使用PyMySQL连接MySQL数据库并执行SQL查询的完整流程,包含驱动安装、连接配置、参数化查询防注入、字典游标使用、结果集提取及资源安全释放的实用代码示例与常见排错指南。

在 Python 中执行 MySQL 数据库查询,最通用且规范的做法是遵循 Python 数据库 API 规范(PEP 249),使用成熟的纯 Python 驱动 PyMySQL。整个过程主要包含四个步骤:安装驱动并导入模块、配置连接参数建立 Connection 对象、创建 Cursor 游标执行参数化 SQL 语句、解析提取结果集并安全释放连接资源。本文提供开箱即用的完整代码示例,并详细解析参数化防注入、字典游标映射以及常见排错细节。
Python连接MySQL执行SQL查询的完整代码示例
图 1:Python 应用与 MySQL 数据库标准查询交互架构概览

一、前置准备:驱动安装与测试数据表

连接 MySQL 需要在 Python 环境中安装兼容 PEP 249 标准的数据库驱动。最常用的驱动是 PyMySQL,其优势在于纯 Python 编写,无需依赖本地 C 语言编译环境或复杂的第三方客户端动态链接库,直接通过 pip 即可完成安装:

pip install pymysql

为了让后续的代码示例能够真实运行并验证输出,假定我们在 MySQL 中创建了一个名为 demo_db 的数据库,并有一张员工表 employees。其结构与测试数据可以通过以下 SQL 语句进行初始化:

-- 创建测试数据库并指定字符集为 utf8mb4
CREATE DATABASE IF NOT EXISTS demo_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE demo_db;

-- 创建员工信息表
CREATE TABLE IF NOT EXISTS employees (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    department VARCHAR(50) NOT NULL,
    salary DECIMAL(10, 2) NOT NULL,
    hire_date DATE NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 插入基础测试数据
INSERT INTO employees (name, department, salary, hire_date) VALUES
('张伟', '技术部', 15000.00, '2022-03-15'),
('李娜', '运营部', 9500.00, '2021-07-01'),
('王强', '技术部', 18500.00, '2020-11-20'),
('赵敏', '产品部', 13000.00, '2023-02-10');

二、标准操作流程与生命周期

一次完整的数据库查询生命周期应严格保证“用后即关”,防止连接句柄挂起导致数据库连接池耗尽。标准步骤包括:定义配置字典、建立连接、获取游标、执行带参查询、读取数据、关闭游标与连接。

Python连接MySQL执行SQL查询的完整代码示例
图 2:Python 执行 MySQL 查询的标准步骤与资源生命周期

三、核心代码实现:基础查询与上下文管理器

在编写生产级代码时,推荐使用 Python 的 with 上下文管理器来管理游标和连接,它可以在代码执行完毕或中途发生异常时自动触发 close(),避免资源泄漏。下面是推荐的完整查询脚本:

# -*- coding: utf-8 -*-
import pymysql
from pymysql.cursors import DictCursor

# 1. 定义数据库连接参数字典
db_config = {
    "host": "127.0.0.1",        # 数据库主机IP或域名
    "port": 3306,               # MySQL 服务端口,默认 3306
    "user": "root",             # 数据库登录用户名
    "password": "YourPassword", # 数据库登录密码
    "database": "demo_db",      # 目标数据库名
    "charset": "utf8mb4",       # 务必指定 utf8mb4,兼容完整中文字符与Emoji
    "cursorclass": DictCursor,  # 使用字典游标,使查询结果以字典键值对返回
    "connect_timeout": 10       # 连接超时时间(秒)
}

def query_employees_by_department(dept_name, min_salary):
    """
    查询指定部门且薪资高于指定金额的员工记录
    """
    connection = None
    try:
        # 2. 建立数据库物理连接
        connection = pymysql.connect(**db_config)
        
        # 3. 使用 with 语句创建游标对象(执行完毕后自动关闭游标)
        with connection.cursor() as cursor:
            # 4. 编写带占位符的 SQL 模板,严禁使用 % 或 + 拼接字符串
            sql = """
                SELECT id, name, department, salary, hire_date
                FROM employees
                WHERE department = %s AND salary >= %s
                ORDER BY salary DESC
            """
            params = (dept_name, min_salary)

            # 5. 执行参数化查询
            rows_matched = cursor.execute(sql, params)
            print(f"[INFO] 查询命中记录数: {rows_matched}")

            # 6. 获取查询结果
            results = cursor.fetchall()
            return results

    except pymysql.MySQLError as err:
        print(f"[ERROR] 数据库操作异常: {err}")
        return []
    finally:
        # 7. 在 finally 块中确保连接无论如何都被安全关闭
        if connection and connection.open:
            connection.close()
            print("[INFO] 数据库连接已安全关闭。")

# 示例调用
if __name__ == "__main__":
    dept = "技术部"
    salary_threshold = 16000.00
    print(f"正在查询【{dept}】部门中薪资大于等于 {salary_threshold} 的员工...")
    
    emp_list = query_employees_by_department(dept, salary_threshold)
    for emp in emp_list:
        # 因为使用了 DictCursor,每一行都是可以直接按列名索引的字典
        print(f"ID: {emp['id']} | 姓名: {emp['name']} | 薪资: {emp['salary']} | 入职: {emp['hire_date']}")

运行输出(示例输出):

正在查询【技术部】部门中薪资大于等于 16000.0 的员工...
[INFO] 查询命中记录数: 1
ID: 3 | 姓名: 王强 | 薪资: 18500.00 | 入职: 2020-11-20
[INFO] 数据库连接已安全关闭。

四、结果集读取模式:fetchone、fetchall 与 fetchmany

执行 cursor.execute() 成功后,数据已从 MySQL 数据库传输到客户端的通信缓存中。此时必须通过游标的获取方法读取行数据。不同方法适用于不同的场景与数据量级:

提取方法 返回数据类型 无数据时返回值 适用场景与内存考量
cursor.fetchone() 单个元组 / 字典 None 根据主键或唯一索引查找单条记录;客户端内存开销极小。
cursor.fetchmany(size) 列表(含多个元组 / 字典) 空列表 [] 中大型数据集流式分批读取,兼顾循环执行效率与内存可控性。
cursor.fetchall() 元组或列表(含全量行) 空集合 小型数据集或明确限制了 LIMIT 的查询;大表全量拉取会导致内存爆满。
Python连接MySQL执行SQL查询的完整代码示例
图 3:游标的三种数据获取模式与客户端内存表现对比

例如,对于批量数据处理,使用 fetchmany 分批循环迭代的代码模式如下:

with connection.cursor() as cursor:
    cursor.execute("SELECT id, name FROM employees")
    batch_size = 2
    while True:
        rows = cursor.fetchmany(batch_size)
        if not rows:
            break  # 所有批次读取完毕
        for row in rows:
            print(f"处理员工: {row['name']}")

五、安全红线:参数化查询与 SQL 注入防范

在任何需要代入外部变量(如表单输入、URL 参数)的 SQL 查询中,严禁使用 Python 的 % 操作符、format() 方法或 f-string 字符串插值拼接 SQL。

字符串拼接将用户输入直接融入语法解析,攻击者可输入 ' OR '1'='1 篡改逻辑。而参数化查询将 SQL 语句和参数作为独立单元传递给驱动,驱动层会自动对参数进行严格转义并作为纯字面量(Literal Value)处理,从根本上杜绝语法逻辑被篡改。

Python连接MySQL执行SQL查询的完整代码示例
图 4:字符串拼接的注入攻击原理与参数化安全防线对比
特别提醒:占位符语法规则
在 PyMySQL 和大多数符合 PEP 249 的 MySQL 驱动中,占位符始终使用 %s,无论字段是整数、浮点数、字符串还是日期,都统一使用 %s,且在 SQL 语句中切勿给 %s 加上引号(例如写成 '%s' 是错误的,会导致引号被视为字面量)。传入的参数必须以元组(Tuple)或列表(List)的形式作为 execute() 的第二个参数。如果只有一个参数,注意 Python 单元素元组末尾要带逗号,如 (dept_name,)。

六、生产环境常见问题与排错指南

在实际部署与运行 Python 连接 MySQL 代码时,常见的报错原因和排查方式如下:

  • 报错 OperationalError: (1045, "Access denied for user..."):
    账号或密码不正确,或者该账号未被允许从当前客户端 IP 登录。可登录 MySQL 服务器检查 mysql.user 表中的 host 字段配置。
  • 报错 OperationalError: (2003, "Can't connect to MySQL server..."):
    通常是网络不通、MySQL 服务未启动、服务器防火墙阻挡了 3306 端口,或者 MySQL 配置中的 bind-address 被限制为 127.0.0.1 导致无法远程访问。
  • 中文乱码或 Emoji 存储截断报错 Incorrect string value:
    连接参数中的 charset 务必明确设置为 utf8mb4。MySQL 历史上的 utf8 仅支持最多 3 字节字符,当遇到 4 字节的 Emoji 或生僻汉字时会报错。
  • 关于 conn.commit() 的调用时机:
    执行 SELECT 查询操作时,属于只读操作,不需要调用 connection.commit();只有执行 INSERT、UPDATE、DELETE 等涉及写事务的操作时,才必须显式调用 conn.commit() 提交事务,否则数据更改不会持久化到磁盘。

七、总结与生产速查

掌握 Python 与 MySQL 的查询交互,关键在于建立规范的编码习惯:严格采用参数化传递防止安全隐患、根据查询规模合理挑选获取模式、并在上下文管理器中完备处理连接与游标的生命周期。

Python连接MySQL执行SQL查询的完整代码示例
图 5:Python 连接 MySQL 核心配置参数矩阵与生产最佳实践总结

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。