15、Python 访问数据库

一、概述

Python操作数据库一般有三种方式:

  1. 原生驱动直接写SQL:sqlite3(内置SQLite)、pymysql(MySQL)
  2. ORM框架 SQLAlchemy:用Python对象映射数据库表,减少手写SQL,适配多种数据库
  3. 适用场景:小测试用SQLite;业务存储用MySQL;项目开发优先SQLAlchemy

遵循数据库通用规范:先建连接 → 获取游标 → 执行SQL → 提交事务 → 关闭游标和连接


二、使用 SQLite

SQLite是文件型数据库,Python内置sqlite3模块,无需额外安装,不需要单独启动服务,适合本地测试、小型数据存储。

基础示例

复制代码
import sqlite3

# 1. 连接数据库,不存在则自动创建文件 test.db
conn = sqlite3.connect("test.db")
# 2. 获取游标
cursor = conn.cursor()

# 建表
cursor.execute('''
CREATE TABLE IF NOT EXISTS user (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    age INTEGER
)
''')

# 插入单条数据
cursor.execute("INSERT INTO user(name, age) VALUES (?, ?)", ("zhangsan", 20))
# 批量插入
cursor.executemany("INSERT INTO user(name, age) VALUES (?, ?)", [
    ("lisi", 22),
    ("wangwu", 21)
])

# 查询
cursor.execute("SELECT * FROM user")
print(cursor.fetchall())   # 全部结果
# cursor.fetchone() 取第一条
# cursor.fetchmany(2) 取前2条

# 更新
cursor.execute("UPDATE user SET age=? WHERE name=?", (25, "zhangsan"))
# 删除
cursor.execute("DELETE FROM user WHERE name=?", ("wangwu",))

# 提交事务(DML操作必须commit,SQLite默认事务)
conn.commit()

# 关闭
cursor.close()
conn.close()

占位符:SQLite 使用 ?,不要用字符串拼接SQL,防止SQL注入


三、使用 MySQL

MySQL是C/S架构数据库,需要先安装MySQL服务,Python使用pymysql驱动。

1. 安装

复制代码
pip install pymysql

2. 基础示例

复制代码
import pymysql

# 建立连接
conn = pymysql.connect(
    host="127.0.0.1",
    port=3306,
    user="root",
    password="你的密码",
    database="test_db",
    charset="utf8mb4"
)
cursor = conn.cursor()

# 建表
cursor.execute('''
CREATE TABLE IF NOT EXISTS user(
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50),
    age INT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
''')

# 插入,pymysql占位符是 %s
cursor.execute("INSERT INTO user(name,age) VALUES (%s,%s)", ("zhangsan",20))
conn.commit()

# 查询
cursor.execute("SELECT * FROM user")
print(cursor.fetchall())

cursor.close()
conn.close()

✅ 重点区别:

  • pymysql 占位符是 %s,不是字符串格式化!
  • 必须提前建好数据库(CREATE DATABASE test_db;)
  • 异常场景:网络断开、账号密码错误、库不存在

异常捕获模板

复制代码
import pymysql
try:
    conn = pymysql.connect(...)
    cursor = conn.cursor()
    cursor.execute(sql)
    conn.commit()
except pymysql.MySQLError as e:
    print("数据库错误:", e)
    conn.rollback()  # 出错回滚
finally:
    if conn:
        cursor.close()
        conn.close()

四、使用 SQLAlchemy

SQLAlchemy 是Python最经典的ORM(对象关系映射)框架,一套代码可以切换 SQLite / MySQL / PostgreSQL,不用大量改SQL。 分为两种使用方式:

  1. Core:SQL表达式方式
  2. ORM:面向对象,类映射表(日常开发最常用)

1. 安装

复制代码
pip install sqlalchemy

2. ORM 完整示例(MySQL)

复制代码
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import declarative_base, sessionmaker

# 1. 创建引擎,连接数据库
# mysql+pymysql://user:password@host:port/dbname
engine = create_engine("mysql+pymysql://root:密码@127.0.0.1:3306/test_db")
# SQLite引擎写法:engine = create_engine("sqlite:///test.db")

# 2. 基类,所有模型继承它
Base = declarative_base()

# 3. 定义模型类(对应数据库一张表)
class User(Base):
    __tablename__ = "user"
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(50), nullable=False)
    age = Column(Integer)

    def __repr__(self):
        return f"<User(name={self.name}, age={self.age})>"

# 4. 创建表(不存在才创建)
Base.metadata.create_all(engine)

# 5. 创建会话,用来增删改查
Session = sessionmaker(bind=engine)
session = Session()

# 新增
u1 = User(name="zhangsan", age=20)
session.add(u1)
session.add_all([
    User(name="lisi", age=22),
    User(name="wangwu", age=21)
])
session.commit()

# 查询
# 查询所有
res = session.query(User).all()
# 条件查询
res = session.query(User).filter(User.name == "zhangsan").first()
# 模糊查询 filter(User.name.like("%zhang%"))

# 更新
if res:
    res.age = 26
    session.commit()

# 删除
session.delete(res)
session.commit()

session.close()

常用查询语法速记

复制代码
# 等于
filter(User.name == "xxx")
# 大于小于
filter(User.age > 18)
# and / or
from sqlalchemy import or_, and_
filter(or_(User.age>20, User.name=="lisi"))
# 排序
order_by(User.age.desc())
# 分页 offset limit
session.query(User).order_by(User.id).offset(0).limit(10).all()

五、三者对比总结

方式 依赖 优点 缺点 适合场景
sqlite3 内置 零服务、开箱即用 并发弱、不适合多用户 本地缓存、脚本、测试
pymysql原生 需要MySQL服务 灵活,完全掌控SQL 重复样板代码,容易注入,切换数据库改动大 简单脚本、需要精细控制SQL
SQLAlchemy ORM 驱动+框架 面向对象、跨数据库、防注入、代码优雅 有学习成本,复杂SQL性能不如手写 Web项目、后端业务开发

六、重要注意事项

  1. 永远不要字符串拼接SQL,使用参数化查询,防止SQL注入
  2. 写修改操作(insert/update/delete)一定要 commit,异常时 rollback
  3. 用完连接、游标、session要关闭,避免连接泄漏
  4. MySQL注意编码 utf8mb4 支持emoji
  5. SQLAlchemy适合业务开发;报表、超复杂聚合SQL可以用原生SQL
相关推荐
秋风点枝1 小时前
数据库 01 · 体系结构与存储引擎
数据库·mysql
~~刘杨1 小时前
用 Python 批量处理商品图:抠图、高清放大与图生视频(同步 API 完整示例)
图像处理·python·aigc
小小张说故事1 小时前
Python 拼字符串为什么别在循环里用 +=?拆开 join 的两遍账:191.8 微秒与 6.8 微秒
python
小此方1 小时前
Re:Mysql数据库基础篇(五):拒绝脏数据!一文吃透MySQL表的约束(主键、唯一键、外键与实战案例)
数据库·mysql
用户298698530141 小时前
Python 实现 Markdown 与 Word 文档互转
python·api·markdown
EnCi Zheng1 小时前
AI Agent工具调用防护层怎么写-一份能直接跑的Python四层拦截实现
大数据·开发语言·python
2601_949847751 小时前
Cookie 跨端三方库仓颉适配全流程
python·django·flask
万粉变现经纪人1 小时前
如何解决 pip install 安装报错 检测到 yanked 版本需更换可用版本 问题
人工智能·python·scrapy·numpy·pandas·pyqt·pip
香蕉大香蕉(06敬畏市场)1 小时前
高频八股 · Java 并发编程(10):异步、ThreadLocal 与虚拟线程(收官)
java·开发语言·网络·jvm·python·ai·实习