当前位置 主页 > 技术大全 >

    告别SQL注入:详解Python中MySQL参数化查询的正确使用方法

    栏目:技术大全 时间:2025-09-24 21:10

    ‍今天详细讲解一下在 Python 中连接 MySQL 数据库的几种主流方法。这将是一个从基础到进阶的完整指南。
    核心库选择
    在 Python 中连接 MySQL,主要有两个流行的驱动:
    1. mysql-connector-python: MySQL 官方提供的纯 Python 驱动。无需其他依赖,安装简单。
    2. PyMySQL: 一个纯 Python 的 MySQL 客户端,兼容性很好,非常流行。
    3. (底层驱动) MySQLdb: 一个 C 扩展模块,速度很快,但在 Python 3 上安装可能较麻烦,通常被 PyMySQL 替代。
    对于现代项目,PyMySQL 和 mysql-connector-python 是最常见的选择。本指南将以 `PyMySQL` 和 `SQLAlchemy` 为例。
    方法一:使用 PyMySQL 直接连接(基础方法)
    这种方式提供了最直接的 SQL 操作,适合需要完全控制 SQL 语句的场景。
    1. 安装库
     
    ```bash
    pip install pymysql
    ```
     
    2. 基本连接与操作流程
     
    完整的操作流程遵循 连接 -> 创建游标 -> 执行SQL -> 提交 -> 关闭 的步骤。
     
    ```python
    import pymysql
    from pymysql.cursors import DictCursor 可选,用于获取字典格式的结果
     
    1. 建立数据库连接
    connection = pymysql.connect(
    host='localhost', 数据库服务器地址,本地可用 localhost 或 127.0.0.1
    user='your_username', 用户名
    password='your_password', 密码
    database='your_database_name', 要连接的数据库名
    charset='utf8mb4', 字符集,支持中文和表情符号推荐 utf8mb4
    cursorclass=DictCursor 可选:设置游标类型,返回字典而非元组
    )
     
    try:
    2. 创建一个游标对象,用于执行SQL语句
    with connection.cursor() as cursor:
    示例1: 执行一条 SELECT 查询
    sql = "SELECT `id`, `name` FROM `users` WHERE `email` = %s"
    cursor.execute(sql, ('user@example.com',)) 使用参数化查询,防止SQL注入!
    获取结果
    result = cursor.fetchone() 获取单条记录
    print(result) 如果是DictCursor,输出: {'id': 1, 'name': 'John'}
    如果用默认游标,输出: (1, 'John')
    获取所有记录
    results = cursor.fetchall()
    for row in results:
    print(row)
     
    示例2: 执行一条 INSERT 语句
    with connection.cursor() as cursor:
    sql = "INSERT INTO `users` (`name`, `email`) VALUES (%s, %s)"
    cursor.execute(sql, ('Alice', 'alice@example.com'))
    3. 提交事务!对于INSERT/UPDATE/DELETE等写操作,必须提交才会生效。
    connection.commit()
     
    示例3: 获取刚插入数据的主键ID
    with connection.cursor() as cursor:
    sql = "INSERT INTO `users` (`name`, `email`) VALUES (%s, %s)"
    cursor.execute(sql, ('Bob', 'bob@example.com'))
    connection.commit()
    print(f"新插入记录的ID是: {cursor.lastrowid}")
     
    finally:
    4. 关闭连接,释放资源
    connection.close()
    ```
     
    3. 使用上下文管理器 (推荐)
     
    为了确保连接总是能被正确关闭,即使发生异常,推荐使用 `with` 语句。
     
    ```python
    import pymysql
     
    使用 with 语句自动管理连接和游标的关闭
    try:
    with pymysql.connect(host='localhost', user='root', password='password', database='test') as conn:
    with conn.cursor() as cursor:
    cursor.execute("SELECT VERSION()")
    result = cursor.fetchone()
    print(f"Database version: {result[0]}")
    连接结束时,如果没有异常,会自动 commit(); 如果有异常,会自动 rollback()
    except pymysql.Error as e:
    print(f"Database error: {e}")
    ```
     
     
     
    方法二:使用 SQLAlchemy (ORM 框架,进阶方法)
     
    ORM (Object-Relational Mapping) 允许你使用 Python 类和对象来操作数据库,而不是直接写 SQL。这对于大型、复杂的项目非常有益,可以提高开发效率和代码可维护性。
     
    1. 安装
     
    ```bash
    pip install sqlalchemy pymysql
    ```
     
    2. 核心组件与连接
     
    ```python
    from sqlalchemy import create_engine, Column, Integer, String
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import sessionmaker
     
    1. 定义数据库连接字符串
    格式: dialect+driver://username:password@host:port/database
    DB_URI = 'mysql+pymysql://username:password@localhost:3306/your_database?charset=utf8mb4'
     
    2. 创建引擎 (Engine),它是ORM和数据库的连接核心
    engine = create_engine(DB_URI, echo=True) echo=True 会打印执行的SQL,调试时有用
     
    3. 创建基类
    Base = declarative_base()
     
    4. 定义映射类(模型)
    class User(Base):
    __tablename__ = 'users' 指定映射的表名
     
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(50), nullable=False)
    email = Column(String(100), unique=True)
     
    5. 创建所有表(如果不存在)
    Base.metadata.create_all(engine)
     
    6. 创建会话工厂 (Session)
    Session = sessionmaker(bind=engine)
     
    7. 使用会话进行增删改查
    新增数据
    with Session() as session:
    new_user = User(name='Charlie', email='charlie@example.com')
    session.add(new_user)
    session.commit() 提交事务
    print(f"New user ID: {new_user.id}") 提交后,id自动赋值
     
    查询数据
    with Session() as session:
    查询所有用户
    users = session.query(User).all()
    for user in users:
    print(user.id, user.name, user.email)
     
    条件查询
    user = session.query(User).filter_by(name='Charlie').first()
    if user:
    print(f"Found user: {user.name}")
    ```
     
     
     
    最佳实践与重要提示
     
    1. 安全第一:永远使用参数化查询
    错误做法(SQL注入风险): `cursor.execute(f"SELECT * FROM users WHERE name = '{user_input}'")`
    正确做法: `cursor.execute("SELECT * FROM users WHERE name = %s", (user_input,))`
    PyMySQL 使用 `%s` 作为占位符,即使数据是数字或日期。
     
    2. 管理敏感信息
    切勿将数据库密码等硬编码在代码中!
    使用环境变量或配置文件(如 `.env` 文件)来管理。
    示例(使用 `python-dotenv`):
    ```bash
    pip install python-dotenv
    ```
    ```python
    .env 文件
    DB_HOST=localhost
    DB_USER=root
    DB_PASSWORD=your_secure_password
    DB_NAME=my_app
    ```
    ```python
    app.py
    from dotenv import load_dotenv
    import os
    import pymysql
     
    load_dotenv() 加载 .env 文件中的环境变量
     
    connection = pymysql.connect(
    host=os.getenv('DB_HOST'),
    user=os.getenv('DB_USER'),
    password=os.getenv('DB_PASSWORD'),
    database=os.getenv('DB_NAME')
    )
    ```
     
    3. 连接管理
    数据库连接是昂贵的资源,一定要确保在使用后正确关闭。强烈推荐使用 `with` 语句上下文管理器。
     
    4. 选择策略
    简单脚本、需要精细控制SQL:选择 PyMySQL 或 mysql-connector-python。
    Web应用、复杂业务逻辑、希望代码更Pythonic:选择 SQLAlchemy ORM。
    另外搭配便捷的MYSQL备份工具,可定时备份、异地备份,MYSQL导出导入。可本地连接LINUX里的MYSQL,简单便捷。可以大大地提高工作效率喔。

1分钟搞定MySQL部署!Docker最强实操指南,含所有常用命令和配置
忘记MySQL密码怎么办?别慌!用这一招跳过验证,轻松重置管理员权限
MySQL自增主键用完怎么办?从原理到实战,全面破解开发中的高频难题
MySQL权限混乱?这几个命令让你彻底理清用户清单与权限归属
你的数据库安全吗?读懂MySQL这几种日志,关键时刻能「救你一命」
MySQL性能上不去?八成是这里没配好!手把手教你搞定my.cnf核心配置
修改MySQL字段长度别乱来!这3个核心要点和1个致命陷阱,新手必看
MySQL单表卡爆怎么办?从策略到实战,一文掌握「分表」救命技巧
你的MySQL数据库为什么总是又慢又卡?掌握这五大优化法则,查询速度快十倍!(上篇)
你的MySQL数据库为什么总是又慢又卡?掌握这五大优化法则,查询速度快十倍!(下篇)